merge
This commit is contained in:
commit
32ab17fa46
27 changed files with 542 additions and 149 deletions
|
@ -24,6 +24,8 @@ clone:
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
image: alpine:3.13
|
image: alpine:3.13
|
||||||
|
environment:
|
||||||
|
TEST_CONTAINER: true
|
||||||
pull: always
|
pull: always
|
||||||
commands:
|
commands:
|
||||||
- scripts/run-full-tests
|
- scripts/run-full-tests
|
||||||
|
|
9
NEWS
9
NEWS
|
@ -1,3 +1,12 @@
|
||||||
|
1.7.11.dev0
|
||||||
|
* #479: Automatically use the "archive_name_format" option to filter which archives get used for
|
||||||
|
borgmatic actions that operate on multiple archives. See the documentation for more information:
|
||||||
|
https://torsion.org/borgmatic/docs/how-to/make-per-application-backups/#archive-naming
|
||||||
|
* #479: The "prefix" options have been deprecated in favor of the new "archive_name_format"
|
||||||
|
auto-matching behavior (see above).
|
||||||
|
* #662: Fix regression in which "check_repositories" option failed to match repositories.
|
||||||
|
* #663: Fix regression in which the "transfer" action produced a traceback.
|
||||||
|
|
||||||
1.7.10
|
1.7.10
|
||||||
* #396: When a database command errors, display and log the error message instead of swallowing it.
|
* #396: When a database command errors, display and log the error message instead of swallowing it.
|
||||||
* #501: Optionally error if a source directory does not exist via "source_directories_must_exist"
|
* #501: Optionally error if a source directory does not exist via "source_directories_must_exist"
|
||||||
|
|
|
@ -17,10 +17,10 @@ def run_transfer(
|
||||||
'''
|
'''
|
||||||
Run the "transfer" action for the given repository.
|
Run the "transfer" action for the given repository.
|
||||||
'''
|
'''
|
||||||
logger.info(f'{repository}: Transferring archives to repository')
|
logger.info(f'{repository["path"]}: Transferring archives to repository')
|
||||||
borgmatic.borg.transfer.transfer_archives(
|
borgmatic.borg.transfer.transfer_archives(
|
||||||
global_arguments.dry_run,
|
global_arguments.dry_run,
|
||||||
repository,
|
repository['path'],
|
||||||
storage,
|
storage,
|
||||||
local_borg_version,
|
local_borg_version,
|
||||||
transfer_arguments,
|
transfer_arguments,
|
||||||
|
|
|
@ -12,7 +12,6 @@ DEFAULT_CHECKS = (
|
||||||
{'name': 'repository', 'frequency': '1 month'},
|
{'name': 'repository', 'frequency': '1 month'},
|
||||||
{'name': 'archives', 'frequency': '1 month'},
|
{'name': 'archives', 'frequency': '1 month'},
|
||||||
)
|
)
|
||||||
DEFAULT_PREFIX = '{hostname}-' # noqa: FS003
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -146,9 +145,10 @@ def filter_checks_on_frequency(
|
||||||
return tuple(filtered_checks)
|
return tuple(filtered_checks)
|
||||||
|
|
||||||
|
|
||||||
def make_check_flags(local_borg_version, checks, check_last=None, prefix=None):
|
def make_check_flags(local_borg_version, storage_config, checks, check_last=None, prefix=None):
|
||||||
'''
|
'''
|
||||||
Given the local Borg version and a parsed sequence of checks, transform the checks into tuple of
|
Given the local Borg version, a storge configuration dict, a parsed sequence of checks, the
|
||||||
|
check last value, and a consistency check prefix, transform the checks into tuple of
|
||||||
command-line flags.
|
command-line flags.
|
||||||
|
|
||||||
For example, given parsed checks of:
|
For example, given parsed checks of:
|
||||||
|
@ -174,10 +174,19 @@ def make_check_flags(local_borg_version, checks, check_last=None, prefix=None):
|
||||||
|
|
||||||
if 'archives' in checks:
|
if 'archives' in checks:
|
||||||
last_flags = ('--last', str(check_last)) if check_last else ()
|
last_flags = ('--last', str(check_last)) if check_last else ()
|
||||||
if feature.available(feature.Feature.MATCH_ARCHIVES, local_borg_version):
|
match_archives_flags = (
|
||||||
match_archives_flags = ('--match-archives', f'sh:{prefix}*') if prefix else ()
|
(
|
||||||
else:
|
('--match-archives', f'sh:{prefix}*')
|
||||||
match_archives_flags = ('--glob-archives', f'{prefix}*') if prefix else ()
|
if feature.available(feature.Feature.MATCH_ARCHIVES, local_borg_version)
|
||||||
|
else ('--glob-archives', f'{prefix}*')
|
||||||
|
)
|
||||||
|
if prefix
|
||||||
|
else (
|
||||||
|
flags.make_match_archives_flags(
|
||||||
|
storage_config.get('archive_name_format'), local_borg_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
last_flags = ()
|
last_flags = ()
|
||||||
match_archives_flags = ()
|
match_archives_flags = ()
|
||||||
|
@ -291,7 +300,7 @@ def check_archives(
|
||||||
extra_borg_options = storage_config.get('extra_borg_options', {}).get('check', '')
|
extra_borg_options = storage_config.get('extra_borg_options', {}).get('check', '')
|
||||||
|
|
||||||
if set(checks).intersection({'repository', 'archives', 'data'}):
|
if set(checks).intersection({'repository', 'archives', 'data'}):
|
||||||
lock_wait = storage_config.get('lock_wait', None)
|
lock_wait = storage_config.get('lock_wait')
|
||||||
|
|
||||||
verbosity_flags = ()
|
verbosity_flags = ()
|
||||||
if logger.isEnabledFor(logging.INFO):
|
if logger.isEnabledFor(logging.INFO):
|
||||||
|
@ -299,12 +308,12 @@ def check_archives(
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
verbosity_flags = ('--debug', '--show-rc')
|
verbosity_flags = ('--debug', '--show-rc')
|
||||||
|
|
||||||
prefix = consistency_config.get('prefix', DEFAULT_PREFIX)
|
prefix = consistency_config.get('prefix')
|
||||||
|
|
||||||
full_command = (
|
full_command = (
|
||||||
(local_path, 'check')
|
(local_path, 'check')
|
||||||
+ (('--repair',) if repair else ())
|
+ (('--repair',) if repair else ())
|
||||||
+ make_check_flags(local_borg_version, checks, check_last, prefix)
|
+ make_check_flags(local_borg_version, storage_config, checks, check_last, prefix)
|
||||||
+ (('--remote-path', remote_path) if remote_path else ())
|
+ (('--remote-path', remote_path) if remote_path else ())
|
||||||
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
|
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
|
||||||
+ verbosity_flags
|
+ verbosity_flags
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import itertools
|
import itertools
|
||||||
|
import re
|
||||||
|
|
||||||
from borgmatic.borg import feature
|
from borgmatic.borg import feature
|
||||||
|
|
||||||
|
@ -56,3 +57,20 @@ def make_repository_archive_flags(repository_path, archive, local_borg_version):
|
||||||
if feature.available(feature.Feature.SEPARATE_REPOSITORY_ARCHIVE, local_borg_version)
|
if feature.available(feature.Feature.SEPARATE_REPOSITORY_ARCHIVE, local_borg_version)
|
||||||
else (f'{repository_path}::{archive}',)
|
else (f'{repository_path}::{archive}',)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def make_match_archives_flags(archive_name_format, local_borg_version):
|
||||||
|
'''
|
||||||
|
Return the match archives flags that would match archives created with the given archive name
|
||||||
|
format (if any). This is done by replacing certain archive name format placeholders for
|
||||||
|
ephemeral data (like "{now}") with globs.
|
||||||
|
'''
|
||||||
|
if not archive_name_format:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
match_archives = re.sub(r'\{(now|utcnow|pid)([:%\w\.-]*)\}', '*', archive_name_format)
|
||||||
|
|
||||||
|
if feature.available(feature.Feature.MATCH_ARCHIVES, local_borg_version):
|
||||||
|
return ('--match-archives', f'sh:{match_archives}')
|
||||||
|
else:
|
||||||
|
return ('--glob-archives', f'{match_archives}')
|
||||||
|
|
|
@ -44,7 +44,11 @@ def display_archives_info(
|
||||||
else flags.make_flags('glob-archives', f'{info_arguments.prefix}*')
|
else flags.make_flags('glob-archives', f'{info_arguments.prefix}*')
|
||||||
)
|
)
|
||||||
if info_arguments.prefix
|
if info_arguments.prefix
|
||||||
else ()
|
else (
|
||||||
|
flags.make_match_archives_flags(
|
||||||
|
storage_config.get('archive_name_format'), local_borg_version
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
+ flags.make_flags_from_arguments(
|
+ flags.make_flags_from_arguments(
|
||||||
info_arguments, excludes=('repository', 'archive', 'prefix')
|
info_arguments, excludes=('repository', 'archive', 'prefix')
|
||||||
|
|
|
@ -7,10 +7,10 @@ from borgmatic.execute import execute_command
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def make_prune_flags(retention_config, local_borg_version):
|
def make_prune_flags(storage_config, retention_config, local_borg_version):
|
||||||
'''
|
'''
|
||||||
Given a retention config dict mapping from option name to value, transform it into an iterable of
|
Given a retention config dict mapping from option name to value, transform it into an sequence of
|
||||||
command-line name-value flag pairs.
|
command-line flags.
|
||||||
|
|
||||||
For example, given a retention config of:
|
For example, given a retention config of:
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ def make_prune_flags(retention_config, local_borg_version):
|
||||||
)
|
)
|
||||||
'''
|
'''
|
||||||
config = retention_config.copy()
|
config = retention_config.copy()
|
||||||
prefix = config.pop('prefix', '{hostname}-') # noqa: FS003
|
prefix = config.pop('prefix', None)
|
||||||
|
|
||||||
if prefix:
|
if prefix:
|
||||||
if feature.available(feature.Feature.MATCH_ARCHIVES, local_borg_version):
|
if feature.available(feature.Feature.MATCH_ARCHIVES, local_borg_version):
|
||||||
|
@ -32,10 +32,16 @@ def make_prune_flags(retention_config, local_borg_version):
|
||||||
else:
|
else:
|
||||||
config['glob_archives'] = f'{prefix}*'
|
config['glob_archives'] = f'{prefix}*'
|
||||||
|
|
||||||
return (
|
flag_pairs = (
|
||||||
('--' + option_name.replace('_', '-'), str(value)) for option_name, value in config.items()
|
('--' + option_name.replace('_', '-'), str(value)) for option_name, value in config.items()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return tuple(
|
||||||
|
element for pair in flag_pairs for element in pair
|
||||||
|
) + flags.make_match_archives_flags(
|
||||||
|
storage_config.get('archive_name_format'), local_borg_version
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def prune_archives(
|
def prune_archives(
|
||||||
dry_run,
|
dry_run,
|
||||||
|
@ -60,11 +66,7 @@ def prune_archives(
|
||||||
|
|
||||||
full_command = (
|
full_command = (
|
||||||
(local_path, 'prune')
|
(local_path, 'prune')
|
||||||
+ tuple(
|
+ make_prune_flags(storage_config, retention_config, local_borg_version)
|
||||||
element
|
|
||||||
for pair in make_prune_flags(retention_config, local_borg_version)
|
|
||||||
for element in pair
|
|
||||||
)
|
|
||||||
+ (('--remote-path', remote_path) if remote_path else ())
|
+ (('--remote-path', remote_path) if remote_path else ())
|
||||||
+ (('--umask', str(umask)) if umask else ())
|
+ (('--umask', str(umask)) if umask else ())
|
||||||
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
|
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
|
||||||
|
|
|
@ -94,7 +94,11 @@ def make_rlist_command(
|
||||||
else flags.make_flags('glob-archives', f'{rlist_arguments.prefix}*')
|
else flags.make_flags('glob-archives', f'{rlist_arguments.prefix}*')
|
||||||
)
|
)
|
||||||
if rlist_arguments.prefix
|
if rlist_arguments.prefix
|
||||||
else ()
|
else (
|
||||||
|
flags.make_match_archives_flags(
|
||||||
|
storage_config.get('archive_name_format'), local_borg_version
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
+ flags.make_flags_from_arguments(rlist_arguments, excludes=MAKE_FLAGS_EXCLUDES)
|
+ flags.make_flags_from_arguments(rlist_arguments, excludes=MAKE_FLAGS_EXCLUDES)
|
||||||
+ flags.make_repository_flags(repository_path, local_borg_version)
|
+ flags.make_repository_flags(repository_path, local_borg_version)
|
||||||
|
|
|
@ -34,9 +34,16 @@ def transfer_archives(
|
||||||
'match-archives', transfer_arguments.match_archives or transfer_arguments.archive
|
'match-archives', transfer_arguments.match_archives or transfer_arguments.archive
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
+ flags.make_flags_from_arguments(
|
+ (
|
||||||
transfer_arguments,
|
flags.make_flags_from_arguments(
|
||||||
excludes=('repository', 'source_repository', 'archive', 'match_archives'),
|
transfer_arguments,
|
||||||
|
excludes=('repository', 'source_repository', 'archive', 'match_archives'),
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
flags.make_match_archives_flags(
|
||||||
|
storage_config.get('archive_name_format'), local_borg_version
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
+ flags.make_repository_flags(repository_path, local_borg_version)
|
+ flags.make_repository_flags(repository_path, local_borg_version)
|
||||||
+ flags.make_flags('other-repo', transfer_arguments.source_repository)
|
+ flags.make_flags('other-repo', transfer_arguments.source_repository)
|
||||||
|
|
|
@ -378,11 +378,9 @@ properties:
|
||||||
description: |
|
description: |
|
||||||
Name of the archive. Borg placeholders can be used. See the
|
Name of the archive. Borg placeholders can be used. See the
|
||||||
output of "borg help placeholders" for details. Defaults to
|
output of "borg help placeholders" for details. Defaults to
|
||||||
"{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f}". If you specify this
|
"{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f}". When running
|
||||||
option, consider also specifying a prefix in the retention
|
actions like rlist, info, or check, borgmatic automatically
|
||||||
and consistency sections to avoid accidental
|
tries to match only archives created with this name format.
|
||||||
pruning/checking of archives with different archive name
|
|
||||||
formats.
|
|
||||||
example: "{hostname}-documents-{now}"
|
example: "{hostname}-documents-{now}"
|
||||||
relocated_repo_access_is_ok:
|
relocated_repo_access_is_ok:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
@ -477,10 +475,12 @@ properties:
|
||||||
prefix:
|
prefix:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
When pruning, only consider archive names starting with this
|
Deprecated. When pruning, only consider archive names
|
||||||
prefix. Borg placeholders can be used. See the output of
|
starting with this prefix. Borg placeholders can be used.
|
||||||
"borg help placeholders" for details. Defaults to
|
See the output of "borg help placeholders" for details.
|
||||||
"{hostname}-". Use an empty value to disable the default.
|
If a prefix is not specified, borgmatic defaults to
|
||||||
|
matching archives based on the archive_name_format (see
|
||||||
|
above).
|
||||||
example: sourcehostname
|
example: sourcehostname
|
||||||
consistency:
|
consistency:
|
||||||
type: object
|
type: object
|
||||||
|
@ -538,12 +538,12 @@ properties:
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
Paths to a subset of the repositories in the location
|
Paths or labels for a subset of the repositories in the
|
||||||
section on which to run consistency checks. Handy in case
|
location section on which to run consistency checks. Handy
|
||||||
some of your repositories are very large, and so running
|
in case some of your repositories are very large, and so
|
||||||
consistency checks on them would take too long. Defaults to
|
running consistency checks on them would take too long.
|
||||||
running consistency checks on all repositories configured in
|
Defaults to running consistency checks on all repositories
|
||||||
the location section.
|
configured in the location section.
|
||||||
example:
|
example:
|
||||||
- user@backupserver:sourcehostname.borg
|
- user@backupserver:sourcehostname.borg
|
||||||
check_last:
|
check_last:
|
||||||
|
@ -556,11 +556,12 @@ properties:
|
||||||
prefix:
|
prefix:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
When performing the "archives" check, only consider archive
|
Deprecated. When performing the "archives" check, only
|
||||||
names starting with this prefix. Borg placeholders can be
|
consider archive names starting with this prefix. Borg
|
||||||
used. See the output of "borg help placeholders" for
|
placeholders can be used. See the output of "borg help
|
||||||
details. Defaults to "{hostname}-". Use an empty value to
|
placeholders" for details. If a prefix is not specified,
|
||||||
disable the default.
|
borgmatic defaults to matching archives based on the
|
||||||
|
archive_name_format (see above).
|
||||||
example: sourcehostname
|
example: sourcehostname
|
||||||
output:
|
output:
|
||||||
type: object
|
type: object
|
||||||
|
|
|
@ -69,7 +69,10 @@ def apply_logical_validation(config_filename, parsed_configuration):
|
||||||
location_repositories = parsed_configuration.get('location', {}).get('repositories')
|
location_repositories = parsed_configuration.get('location', {}).get('repositories')
|
||||||
check_repositories = parsed_configuration.get('consistency', {}).get('check_repositories', [])
|
check_repositories = parsed_configuration.get('consistency', {}).get('check_repositories', [])
|
||||||
for repository in check_repositories:
|
for repository in check_repositories:
|
||||||
if repository not in location_repositories:
|
if not any(
|
||||||
|
repositories_match(repository, config_repository)
|
||||||
|
for config_repository in location_repositories
|
||||||
|
):
|
||||||
raise Validation_error(
|
raise Validation_error(
|
||||||
config_filename,
|
config_filename,
|
||||||
(
|
(
|
||||||
|
|
|
@ -25,7 +25,7 @@ so that you can run borgmatic commands while you're hacking on them to
|
||||||
make sure your changes work.
|
make sure your changes work.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd borgmatic/
|
cd borgmatic
|
||||||
pip3 install --user --editable .
|
pip3 install --user --editable .
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@ pip3 install --user tox
|
||||||
Finally, to actually run tests, run:
|
Finally, to actually run tests, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd borgmatic
|
|
||||||
tox
|
tox
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,71 @@ choice](https://torsion.org/borgmatic/docs/how-to/set-up-backups/#autopilot),
|
||||||
each entry using borgmatic's `--config` flag instead of relying on
|
each entry using borgmatic's `--config` flag instead of relying on
|
||||||
`/etc/borgmatic.d`.
|
`/etc/borgmatic.d`.
|
||||||
|
|
||||||
|
|
||||||
|
## Archive naming
|
||||||
|
|
||||||
|
If you've got multiple borgmatic configuration files, you might want to create
|
||||||
|
archives with different naming schemes for each one. This is especially handy
|
||||||
|
if each configuration file is backing up to the same Borg repository but you
|
||||||
|
still want to be able to distinguish backup archives for one application from
|
||||||
|
another.
|
||||||
|
|
||||||
|
borgmatic supports this use case with an `archive_name_format` option. The
|
||||||
|
idea is that you define a string format containing a number of [Borg
|
||||||
|
placeholders](https://borgbackup.readthedocs.io/en/stable/usage/help.html#borg-placeholders),
|
||||||
|
and borgmatic uses that format to name any new archive it creates. For
|
||||||
|
instance:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
location:
|
||||||
|
...
|
||||||
|
archive_name_format: home-directories-{now}
|
||||||
|
```
|
||||||
|
|
||||||
|
This means that when borgmatic creates an archive, its name will start with
|
||||||
|
the string `home-directories-` and end with a timestamp for its creation time.
|
||||||
|
If `archive_name_format` is unspecified, the default is
|
||||||
|
`{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f}`, meaning your system hostname plus a
|
||||||
|
timestamp in a particular format.
|
||||||
|
|
||||||
|
<span class="minilink minilink-addedin">New in version 1.7.11</span> borgmatic
|
||||||
|
uses the `archive_name_format` option to automatically limit which archives
|
||||||
|
get used for actions operating on multiple archives. This prevents, for
|
||||||
|
instance, duplicate archives from showing up in `rlist` or `info` results—even
|
||||||
|
if the same repository appears in multiple borgmatic configuration files. To
|
||||||
|
take advantage of this feature, simply use a different `archive_name_format`
|
||||||
|
in each configuration file.
|
||||||
|
|
||||||
|
Under the hood, borgmatic accomplishes this by substituting globs for certain
|
||||||
|
ephemeral data placeholders in your `archive_name_format`—and using the result
|
||||||
|
to filter archives when running supported actions.
|
||||||
|
|
||||||
|
For instance, let's say that you have this in your configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
location:
|
||||||
|
...
|
||||||
|
archive_name_format: {hostname}-user-data-{now}
|
||||||
|
```
|
||||||
|
|
||||||
|
borgmatic considers `{now}` an emphemeral data placeholder that will probably
|
||||||
|
change per archive, while `{hostname}` won't. So it turns the example value
|
||||||
|
into `{hostname}-user-data-*` and applies it to filter down the set of
|
||||||
|
archives used for actions like `rlist`, `info`, `prune`, `check`, etc.
|
||||||
|
|
||||||
|
The end result is that when borgmatic runs the actions for a particular
|
||||||
|
application-specific configuration file, it only operates on the archives
|
||||||
|
created for that application. Of course, this doesn't apply to actions like
|
||||||
|
`compact` that operate on an entire repository.
|
||||||
|
|
||||||
|
<span class="minilink minilink-addedin">Prior to 1.7.11</span> The way to
|
||||||
|
limit the archives used for the `prune` action was a `prefix` option in the
|
||||||
|
`retention` section for matching against the start of archive names. And the
|
||||||
|
option for limiting the archives used for the `check` action was a separate
|
||||||
|
`prefix` in the `consistency` section. Both of these options are deprecated in
|
||||||
|
favor of the auto-matching behavior in newer versions of borgmatic.
|
||||||
|
|
||||||
|
|
||||||
## Configuration includes
|
## Configuration includes
|
||||||
|
|
||||||
Once you have multiple different configuration files, you might want to share
|
Once you have multiple different configuration files, you might want to share
|
||||||
|
@ -272,7 +337,7 @@ Here's an example usage:
|
||||||
```yaml
|
```yaml
|
||||||
constants:
|
constants:
|
||||||
user: foo
|
user: foo
|
||||||
my_prefix: bar-
|
archive_prefix: bar
|
||||||
|
|
||||||
location:
|
location:
|
||||||
source_directories:
|
source_directories:
|
||||||
|
@ -281,20 +346,14 @@ location:
|
||||||
...
|
...
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
archive_name_format: '{my_prefix}{now}'
|
archive_name_format: '{archive_prefix}-{now}'
|
||||||
|
|
||||||
retention:
|
|
||||||
prefix: {my_prefix}
|
|
||||||
|
|
||||||
consistency:
|
|
||||||
prefix: {my_prefix}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, when borgmatic runs, all instances of `{user}` get replaced
|
In this example, when borgmatic runs, all instances of `{user}` get replaced
|
||||||
with `foo` and all instances of `{my_prefix}` get replaced with `bar-`. (And
|
with `foo` and all instances of `{archive-prefix}` get replaced with `bar-`.
|
||||||
in this particular example, `{now}` doesn't get replaced with anything, but
|
(And in this particular example, `{now}` doesn't get replaced with anything,
|
||||||
gets passed directly to Borg.) After substitution, the logical result looks
|
but gets passed directly to Borg.) After substitution, the logical result
|
||||||
something like this:
|
looks something like this:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
location:
|
location:
|
||||||
|
@ -305,12 +364,6 @@ location:
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
archive_name_format: 'bar-{now}'
|
archive_name_format: 'bar-{now}'
|
||||||
|
|
||||||
retention:
|
|
||||||
prefix: bar-
|
|
||||||
|
|
||||||
consistency:
|
|
||||||
prefix: bar-
|
|
||||||
```
|
```
|
||||||
|
|
||||||
An alternate to constants is passing in your values via [environment
|
An alternate to constants is passing in your values via [environment
|
||||||
|
|
|
@ -90,7 +90,7 @@ installing borgmatic:
|
||||||
* [Fedora unofficial](https://copr.fedorainfracloud.org/coprs/heffer/borgmatic/)
|
* [Fedora unofficial](https://copr.fedorainfracloud.org/coprs/heffer/borgmatic/)
|
||||||
* [Arch Linux](https://www.archlinux.org/packages/community/any/borgmatic/)
|
* [Arch Linux](https://www.archlinux.org/packages/community/any/borgmatic/)
|
||||||
* [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=borgmatic)
|
* [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=borgmatic)
|
||||||
* [OpenBSD](http://ports.su/sysutils/borgmatic)
|
* [OpenBSD](https://openports.pl/path/sysutils/borgmatic)
|
||||||
* [openSUSE](https://software.opensuse.org/package/borgmatic)
|
* [openSUSE](https://software.opensuse.org/package/borgmatic)
|
||||||
* [macOS (via Homebrew)](https://formulae.brew.sh/formula/borgmatic)
|
* [macOS (via Homebrew)](https://formulae.brew.sh/formula/borgmatic)
|
||||||
* [macOS (via MacPorts)](https://ports.macports.org/port/borgmatic/)
|
* [macOS (via MacPorts)](https://ports.macports.org/port/borgmatic/)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# This script is for running all tests, including end-to-end tests, on a developer machine. It sets
|
# This script is for running end-to-end tests on a developer machine. It sets up database containers
|
||||||
# up database containers to run tests against, runs the tests, and then tears down the containers.
|
# to run tests against, runs the tests, and then tears down the containers.
|
||||||
#
|
#
|
||||||
# Run this script from the root directory of the borgmatic source.
|
# Run this script from the root directory of the borgmatic source.
|
||||||
#
|
#
|
||||||
|
|
|
@ -8,7 +8,14 @@
|
||||||
# For more information, see:
|
# For more information, see:
|
||||||
# https://torsion.org/borgmatic/docs/how-to/develop-on-borgmatic/
|
# https://torsion.org/borgmatic/docs/how-to/develop-on-borgmatic/
|
||||||
|
|
||||||
set -ex
|
set -e
|
||||||
|
|
||||||
|
if [ -z "$TEST_CONTAINER" ] ; then
|
||||||
|
echo "This script is designed to work inside a test container and is not intended to"
|
||||||
|
echo "be run manually. If you're trying to run borgmatic's end-to-end tests, execute"
|
||||||
|
echo "scripts/run-end-to-end-dev-tests instead."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
apk add --no-cache python3 py3-pip borgbackup postgresql-client mariadb-client mongodb-tools \
|
apk add --no-cache python3 py3-pip borgbackup postgresql-client mariadb-client mongodb-tools \
|
||||||
py3-ruamel.yaml py3-ruamel.yaml.clib bash sqlite
|
py3-ruamel.yaml py3-ruamel.yaml.clib bash sqlite
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -1,6 +1,6 @@
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
VERSION = '1.7.10'
|
VERSION = '1.7.11.dev0'
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
|
|
@ -17,6 +17,8 @@ services:
|
||||||
MONGO_INITDB_ROOT_PASSWORD: test
|
MONGO_INITDB_ROOT_PASSWORD: test
|
||||||
tests:
|
tests:
|
||||||
image: alpine:3.13
|
image: alpine:3.13
|
||||||
|
environment:
|
||||||
|
TEST_CONTAINER: true
|
||||||
volumes:
|
volumes:
|
||||||
- "../..:/app:ro"
|
- "../..:/app:ro"
|
||||||
tmpfs:
|
tmpfs:
|
||||||
|
@ -28,3 +30,4 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgresql
|
- postgresql
|
||||||
- mysql
|
- mysql
|
||||||
|
- mongodb
|
||||||
|
|
|
@ -147,7 +147,7 @@ def test_log_outputs_kills_other_processes_when_one_errors():
|
||||||
['sleep', '2'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
['sleep', '2'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
flexmock(module).should_receive('exit_code_indicates_error').with_args(
|
flexmock(module).should_receive('exit_code_indicates_error').with_args(
|
||||||
other_process, None, 'borg'
|
['sleep', '2'], None, 'borg'
|
||||||
).and_return(False)
|
).and_return(False)
|
||||||
flexmock(module).should_receive('output_buffer_for_process').with_args(process, ()).and_return(
|
flexmock(module).should_receive('output_buffer_for_process').with_args(process, ()).and_return(
|
||||||
process.stdout
|
process.stdout
|
||||||
|
|
|
@ -10,7 +10,7 @@ def test_run_transfer_does_not_raise():
|
||||||
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
|
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
|
||||||
|
|
||||||
module.run_transfer(
|
module.run_transfer(
|
||||||
repository='repo',
|
repository={'path': 'repo'},
|
||||||
storage={},
|
storage={},
|
||||||
local_borg_version=None,
|
local_borg_version=None,
|
||||||
transfer_arguments=transfer_arguments,
|
transfer_arguments=transfer_arguments,
|
||||||
|
|
|
@ -189,150 +189,170 @@ def test_filter_checks_on_frequency_restains_check_with_unelapsed_frequency_and_
|
||||||
|
|
||||||
def test_make_check_flags_with_repository_check_returns_flag():
|
def test_make_check_flags_with_repository_check_returns_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('repository',))
|
flags = module.make_check_flags('1.2.3', {}, ('repository',))
|
||||||
|
|
||||||
assert flags == ('--repository-only',)
|
assert flags == ('--repository-only',)
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_archives_check_returns_flag():
|
def test_make_check_flags_with_archives_check_returns_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('archives',))
|
flags = module.make_check_flags('1.2.3', {}, ('archives',))
|
||||||
|
|
||||||
assert flags == ('--archives-only',)
|
assert flags == ('--archives-only',)
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_data_check_returns_flag_and_implies_archives():
|
def test_make_check_flags_with_data_check_returns_flag_and_implies_archives():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('data',))
|
flags = module.make_check_flags('1.2.3', {}, ('data',))
|
||||||
|
|
||||||
assert flags == ('--archives-only', '--verify-data',)
|
assert flags == ('--archives-only', '--verify-data',)
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_extract_omits_extract_flag():
|
def test_make_check_flags_with_extract_omits_extract_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('extract',))
|
flags = module.make_check_flags('1.2.3', {}, ('extract',))
|
||||||
|
|
||||||
assert flags == ()
|
assert flags == ()
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_repository_and_data_checks_does_not_return_repository_only():
|
def test_make_check_flags_with_repository_and_data_checks_does_not_return_repository_only():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('repository', 'data',))
|
flags = module.make_check_flags('1.2.3', {}, ('repository', 'data',))
|
||||||
|
|
||||||
assert flags == ('--verify-data',)
|
assert flags == ('--verify-data',)
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_default_checks_and_default_prefix_returns_default_flags():
|
def test_make_check_flags_with_default_checks_and_prefix_returns_default_flags():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
|
flags = module.make_check_flags('1.2.3', {}, ('repository', 'archives'), prefix='foo',)
|
||||||
|
|
||||||
|
assert flags == ('--match-archives', 'sh:foo*')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_check_flags_with_all_checks_and_prefix_returns_default_flags():
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags(
|
flags = module.make_check_flags(
|
||||||
'1.2.3', ('repository', 'archives'), prefix=module.DEFAULT_PREFIX
|
'1.2.3', {}, ('repository', 'archives', 'extract'), prefix='foo',
|
||||||
)
|
)
|
||||||
|
|
||||||
assert flags == ('--match-archives', f'sh:{module.DEFAULT_PREFIX}*')
|
assert flags == ('--match-archives', 'sh:foo*')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_all_checks_and_default_prefix_returns_default_flags():
|
def test_make_check_flags_with_all_checks_and_prefix_without_borg_features_returns_glob_archives_flags():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
|
|
||||||
flags = module.make_check_flags(
|
|
||||||
'1.2.3', ('repository', 'archives', 'extract'), prefix=module.DEFAULT_PREFIX
|
|
||||||
)
|
|
||||||
|
|
||||||
assert flags == ('--match-archives', f'sh:{module.DEFAULT_PREFIX}*')
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_all_checks_and_default_prefix_without_borg_features_returns_glob_archives_flags():
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(False)
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags(
|
flags = module.make_check_flags(
|
||||||
'1.2.3', ('repository', 'archives', 'extract'), prefix=module.DEFAULT_PREFIX
|
'1.2.3', {}, ('repository', 'archives', 'extract'), prefix='foo',
|
||||||
)
|
)
|
||||||
|
|
||||||
assert flags == ('--glob-archives', f'{module.DEFAULT_PREFIX}*')
|
assert flags == ('--glob-archives', 'foo*')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_archives_check_and_last_includes_last_flag():
|
def test_make_check_flags_with_archives_check_and_last_includes_last_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('archives',), check_last=3)
|
flags = module.make_check_flags('1.2.3', {}, ('archives',), check_last=3)
|
||||||
|
|
||||||
assert flags == ('--archives-only', '--last', '3')
|
assert flags == ('--archives-only', '--last', '3')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_data_check_and_last_includes_last_flag():
|
def test_make_check_flags_with_data_check_and_last_includes_last_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('data',), check_last=3)
|
flags = module.make_check_flags('1.2.3', {}, ('data',), check_last=3)
|
||||||
|
|
||||||
assert flags == ('--archives-only', '--last', '3', '--verify-data')
|
assert flags == ('--archives-only', '--last', '3', '--verify-data')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_repository_check_and_last_omits_last_flag():
|
def test_make_check_flags_with_repository_check_and_last_omits_last_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('repository',), check_last=3)
|
flags = module.make_check_flags('1.2.3', {}, ('repository',), check_last=3)
|
||||||
|
|
||||||
assert flags == ('--repository-only',)
|
assert flags == ('--repository-only',)
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_default_checks_and_last_includes_last_flag():
|
def test_make_check_flags_with_default_checks_and_last_includes_last_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('repository', 'archives'), check_last=3)
|
flags = module.make_check_flags('1.2.3', {}, ('repository', 'archives'), check_last=3)
|
||||||
|
|
||||||
assert flags == ('--last', '3')
|
assert flags == ('--last', '3')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_archives_check_and_prefix_includes_match_archives_flag():
|
def test_make_check_flags_with_archives_check_and_prefix_includes_match_archives_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('archives',), prefix='foo-')
|
flags = module.make_check_flags('1.2.3', {}, ('archives',), prefix='foo-')
|
||||||
|
|
||||||
assert flags == ('--archives-only', '--match-archives', 'sh:foo-*')
|
assert flags == ('--archives-only', '--match-archives', 'sh:foo-*')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_data_check_and_prefix_includes_match_archives_flag():
|
def test_make_check_flags_with_data_check_and_prefix_includes_match_archives_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('data',), prefix='foo-')
|
flags = module.make_check_flags('1.2.3', {}, ('data',), prefix='foo-')
|
||||||
|
|
||||||
assert flags == ('--archives-only', '--match-archives', 'sh:foo-*', '--verify-data')
|
assert flags == ('--archives-only', '--match-archives', 'sh:foo-*', '--verify-data')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_archives_check_and_empty_prefix_omits_match_archives_flag():
|
def test_make_check_flags_with_archives_check_and_empty_prefix_uses_archive_name_format_instead():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
'bar-{now}', '1.2.3' # noqa: FS003
|
||||||
|
).and_return(('--match-archives', 'sh:bar-*'))
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('archives',), prefix='')
|
flags = module.make_check_flags(
|
||||||
|
'1.2.3', {'archive_name_format': 'bar-{now}'}, ('archives',), prefix='' # noqa: FS003
|
||||||
|
)
|
||||||
|
|
||||||
assert flags == ('--archives-only',)
|
assert flags == ('--archives-only', '--match-archives', 'sh:bar-*')
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_archives_check_and_none_prefix_omits_match_archives_flag():
|
def test_make_check_flags_with_archives_check_and_none_prefix_omits_match_archives_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('archives',), prefix=None)
|
flags = module.make_check_flags('1.2.3', {}, ('archives',), prefix=None)
|
||||||
|
|
||||||
assert flags == ('--archives-only',)
|
assert flags == ('--archives-only',)
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_repository_check_and_prefix_omits_match_archives_flag():
|
def test_make_check_flags_with_repository_check_and_prefix_omits_match_archives_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('repository',), prefix='foo-')
|
flags = module.make_check_flags('1.2.3', {}, ('repository',), prefix='foo-')
|
||||||
|
|
||||||
assert flags == ('--repository-only',)
|
assert flags == ('--repository-only',)
|
||||||
|
|
||||||
|
|
||||||
def test_make_check_flags_with_default_checks_and_prefix_includes_match_archives_flag():
|
def test_make_check_flags_with_default_checks_and_prefix_includes_match_archives_flag():
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
flags = module.make_check_flags('1.2.3', ('repository', 'archives'), prefix='foo-')
|
flags = module.make_check_flags('1.2.3', {}, ('repository', 'archives'), prefix='foo-')
|
||||||
|
|
||||||
assert flags == ('--match-archives', 'sh:foo-*')
|
assert flags == ('--match-archives', 'sh:foo-*')
|
||||||
|
|
||||||
|
@ -427,7 +447,7 @@ def test_check_archives_calls_borg_with_parameters(checks):
|
||||||
'{"repository": {"id": "repo"}}'
|
'{"repository": {"id": "repo"}}'
|
||||||
)
|
)
|
||||||
flexmock(module).should_receive('make_check_flags').with_args(
|
flexmock(module).should_receive('make_check_flags').with_args(
|
||||||
'1.2.3', checks, check_last, module.DEFAULT_PREFIX
|
'1.2.3', {}, checks, check_last, prefix=None,
|
||||||
).and_return(())
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
insert_execute_command_mock(('borg', 'check', 'repo'))
|
insert_execute_command_mock(('borg', 'check', 'repo'))
|
||||||
|
@ -581,7 +601,7 @@ def test_check_archives_with_local_path_calls_borg_via_local_path():
|
||||||
'{"repository": {"id": "repo"}}'
|
'{"repository": {"id": "repo"}}'
|
||||||
)
|
)
|
||||||
flexmock(module).should_receive('make_check_flags').with_args(
|
flexmock(module).should_receive('make_check_flags').with_args(
|
||||||
'1.2.3', checks, check_last, module.DEFAULT_PREFIX
|
'1.2.3', {}, checks, check_last, prefix=None,
|
||||||
).and_return(())
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
insert_execute_command_mock(('borg1', 'check', 'repo'))
|
insert_execute_command_mock(('borg1', 'check', 'repo'))
|
||||||
|
@ -608,7 +628,7 @@ def test_check_archives_with_remote_path_calls_borg_with_remote_path_parameters(
|
||||||
'{"repository": {"id": "repo"}}'
|
'{"repository": {"id": "repo"}}'
|
||||||
)
|
)
|
||||||
flexmock(module).should_receive('make_check_flags').with_args(
|
flexmock(module).should_receive('make_check_flags').with_args(
|
||||||
'1.2.3', checks, check_last, module.DEFAULT_PREFIX
|
'1.2.3', {}, checks, check_last, prefix=None,
|
||||||
).and_return(())
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
insert_execute_command_mock(('borg', 'check', '--remote-path', 'borg1', 'repo'))
|
insert_execute_command_mock(('borg', 'check', '--remote-path', 'borg1', 'repo'))
|
||||||
|
@ -628,6 +648,7 @@ def test_check_archives_with_remote_path_calls_borg_with_remote_path_parameters(
|
||||||
def test_check_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
def test_check_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
||||||
checks = ('repository',)
|
checks = ('repository',)
|
||||||
check_last = flexmock()
|
check_last = flexmock()
|
||||||
|
storage_config = {'lock_wait': 5}
|
||||||
consistency_config = {'check_last': check_last}
|
consistency_config = {'check_last': check_last}
|
||||||
flexmock(module).should_receive('parse_checks')
|
flexmock(module).should_receive('parse_checks')
|
||||||
flexmock(module).should_receive('filter_checks_on_frequency').and_return(checks)
|
flexmock(module).should_receive('filter_checks_on_frequency').and_return(checks)
|
||||||
|
@ -635,7 +656,7 @@ def test_check_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
||||||
'{"repository": {"id": "repo"}}'
|
'{"repository": {"id": "repo"}}'
|
||||||
)
|
)
|
||||||
flexmock(module).should_receive('make_check_flags').with_args(
|
flexmock(module).should_receive('make_check_flags').with_args(
|
||||||
'1.2.3', checks, check_last, module.DEFAULT_PREFIX
|
'1.2.3', storage_config, checks, check_last, None,
|
||||||
).and_return(())
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
insert_execute_command_mock(('borg', 'check', '--lock-wait', '5', 'repo'))
|
insert_execute_command_mock(('borg', 'check', '--lock-wait', '5', 'repo'))
|
||||||
|
@ -645,7 +666,7 @@ def test_check_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
||||||
module.check_archives(
|
module.check_archives(
|
||||||
repository_path='repo',
|
repository_path='repo',
|
||||||
location_config={},
|
location_config={},
|
||||||
storage_config={'lock_wait': 5},
|
storage_config=storage_config,
|
||||||
consistency_config=consistency_config,
|
consistency_config=consistency_config,
|
||||||
local_borg_version='1.2.3',
|
local_borg_version='1.2.3',
|
||||||
)
|
)
|
||||||
|
@ -662,7 +683,7 @@ def test_check_archives_with_retention_prefix():
|
||||||
'{"repository": {"id": "repo"}}'
|
'{"repository": {"id": "repo"}}'
|
||||||
)
|
)
|
||||||
flexmock(module).should_receive('make_check_flags').with_args(
|
flexmock(module).should_receive('make_check_flags').with_args(
|
||||||
'1.2.3', checks, check_last, prefix
|
'1.2.3', {}, checks, check_last, prefix
|
||||||
).and_return(())
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
insert_execute_command_mock(('borg', 'check', 'repo'))
|
insert_execute_command_mock(('borg', 'check', 'repo'))
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import pytest
|
||||||
from flexmock import flexmock
|
from flexmock import flexmock
|
||||||
|
|
||||||
from borgmatic.borg import flags as module
|
from borgmatic.borg import flags as module
|
||||||
|
@ -78,3 +79,35 @@ def test_make_repository_archive_flags_with_borg_features_joins_repository_and_a
|
||||||
assert module.make_repository_archive_flags(
|
assert module.make_repository_archive_flags(
|
||||||
repository_path='repo', archive='archive', local_borg_version='1.2.3'
|
repository_path='repo', archive='archive', local_borg_version='1.2.3'
|
||||||
) == ('repo::archive',)
|
) == ('repo::archive',)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'archive_name_format,feature_available,expected_result',
|
||||||
|
(
|
||||||
|
(None, True, ()),
|
||||||
|
('', True, ()),
|
||||||
|
(
|
||||||
|
'{hostname}-docs-{now}', # noqa: FS003
|
||||||
|
True,
|
||||||
|
('--match-archives', 'sh:{hostname}-docs-*'), # noqa: FS003
|
||||||
|
),
|
||||||
|
('{utcnow}-docs-{user}', True, ('--match-archives', 'sh:*-docs-{user}')), # noqa: FS003
|
||||||
|
('{fqdn}-{pid}', True, ('--match-archives', 'sh:{fqdn}-*')), # noqa: FS003
|
||||||
|
(
|
||||||
|
'stuff-{now:%Y-%m-%dT%H:%M:%S.%f}', # noqa: FS003
|
||||||
|
True,
|
||||||
|
('--match-archives', 'sh:stuff-*'),
|
||||||
|
),
|
||||||
|
('{hostname}-docs-{now}', False, ('--glob-archives', '{hostname}-docs-*')), # noqa: FS003
|
||||||
|
('{utcnow}-docs-{user}', False, ('--glob-archives', '*-docs-{user}')), # noqa: FS003
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_make_match_archives_flags_makes_flags_with_globs(
|
||||||
|
archive_name_format, feature_available, expected_result
|
||||||
|
):
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(feature_available)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
module.make_match_archives_flags(archive_name_format, local_borg_version=flexmock())
|
||||||
|
== expected_result
|
||||||
|
)
|
||||||
|
|
|
@ -12,6 +12,9 @@ def test_display_archives_info_calls_borg_with_parameters():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -34,6 +37,9 @@ def test_display_archives_info_with_log_info_calls_borg_with_info_parameter():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -56,6 +62,9 @@ def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_outpu
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -78,6 +87,9 @@ def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -101,6 +113,9 @@ def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_outp
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -123,6 +138,9 @@ def test_display_archives_info_with_json_calls_borg_with_json_parameter():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -147,6 +165,9 @@ def test_display_archives_info_with_archive_calls_borg_with_match_archives_param
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args(
|
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||||
'match-archives', 'archive'
|
'match-archives', 'archive'
|
||||||
).and_return(('--match-archives', 'archive'))
|
).and_return(('--match-archives', 'archive'))
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -169,6 +190,9 @@ def test_display_archives_info_with_local_path_calls_borg_via_local_path():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -195,6 +219,9 @@ def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_para
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args(
|
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||||
'remote-path', 'borg1'
|
'remote-path', 'borg1'
|
||||||
).and_return(('--remote-path', 'borg1'))
|
).and_return(('--remote-path', 'borg1'))
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -221,6 +248,9 @@ def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_paramete
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args('lock-wait', 5).and_return(
|
flexmock(module.flags).should_receive('make_flags').with_args('lock-wait', 5).and_return(
|
||||||
('--lock-wait', '5')
|
('--lock-wait', '5')
|
||||||
)
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
storage_config = {'lock_wait': 5}
|
storage_config = {'lock_wait': 5}
|
||||||
|
@ -240,13 +270,16 @@ def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_paramete
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_display_archives_info_with_prefix_calls_borg_with_match_archives_parameters():
|
def test_display_archives_info_transforms_prefix_into_match_archives_parameters():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args(
|
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||||
'match-archives', 'sh:foo*'
|
'match-archives', 'sh:foo*'
|
||||||
).and_return(('--match-archives', 'sh:foo*'))
|
).and_return(('--match-archives', 'sh:foo*'))
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -265,12 +298,68 @@ def test_display_archives_info_with_prefix_calls_borg_with_match_archives_parame
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_display_archives_info_prefers_prefix_over_archive_name_format():
|
||||||
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||||
|
'match-archives', 'sh:foo*'
|
||||||
|
).and_return(('--match-archives', 'sh:foo*'))
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'info', '--match-archives', 'sh:foo*', '--repo', 'repo'),
|
||||||
|
output_log_level=module.borgmatic.logger.ANSWER,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
module.display_archives_info(
|
||||||
|
repository_path='repo',
|
||||||
|
storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
|
||||||
|
local_borg_version='2.3.4',
|
||||||
|
info_arguments=flexmock(archive=None, json=False, prefix='foo'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_display_archives_info_transforms_archive_name_format_into_match_archives_parameters():
|
||||||
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
'bar-{now}', '2.3.4' # noqa: FS003
|
||||||
|
).and_return(('--match-archives', 'sh:bar-*'))
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'info', '--match-archives', 'sh:bar-*', '--repo', 'repo'),
|
||||||
|
output_log_level=module.borgmatic.logger.ANSWER,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
module.display_archives_info(
|
||||||
|
repository_path='repo',
|
||||||
|
storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
|
||||||
|
local_borg_version='2.3.4',
|
||||||
|
info_arguments=flexmock(archive=None, json=False, prefix=None),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('argument_name', ('match_archives', 'sort_by', 'first', 'last'))
|
@pytest.mark.parametrize('argument_name', ('match_archives', 'sort_by', 'first', 'last'))
|
||||||
def test_display_archives_info_passes_through_arguments_to_borg(argument_name):
|
def test_display_archives_info_passes_through_arguments_to_borg(argument_name):
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flag_name = f"--{argument_name.replace('_', ' ')}"
|
flag_name = f"--{argument_name.replace('_', ' ')}"
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '2.3.4'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
||||||
(flag_name, 'value')
|
(flag_name, 'value')
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,18 +18,17 @@ def insert_execute_command_mock(prune_command, output_log_level):
|
||||||
).once()
|
).once()
|
||||||
|
|
||||||
|
|
||||||
BASE_PRUNE_FLAGS = (('--keep-daily', '1'), ('--keep-weekly', '2'), ('--keep-monthly', '3'))
|
BASE_PRUNE_FLAGS = ('--keep-daily', '1', '--keep-weekly', '2', '--keep-monthly', '3')
|
||||||
|
|
||||||
|
|
||||||
def test_make_prune_flags_returns_flags_from_config_plus_default_prefix_glob():
|
def test_make_prune_flags_returns_flags_from_config():
|
||||||
retention_config = OrderedDict((('keep_daily', 1), ('keep_weekly', 2), ('keep_monthly', 3)))
|
retention_config = OrderedDict((('keep_daily', 1), ('keep_weekly', 2), ('keep_monthly', 3)))
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
|
result = module.make_prune_flags({}, retention_config, local_borg_version='1.2.3')
|
||||||
|
|
||||||
assert tuple(result) == BASE_PRUNE_FLAGS + (
|
assert result == BASE_PRUNE_FLAGS
|
||||||
('--match-archives', 'sh:{hostname}-*'), # noqa: FS003
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_prune_flags_accepts_prefix_with_placeholders():
|
def test_make_prune_flags_accepts_prefix_with_placeholders():
|
||||||
|
@ -37,15 +36,18 @@ def test_make_prune_flags_accepts_prefix_with_placeholders():
|
||||||
(('keep_daily', 1), ('prefix', 'Documents_{hostname}-{now}')) # noqa: FS003
|
(('keep_daily', 1), ('prefix', 'Documents_{hostname}-{now}')) # noqa: FS003
|
||||||
)
|
)
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
|
result = module.make_prune_flags({}, retention_config, local_borg_version='1.2.3')
|
||||||
|
|
||||||
expected = (
|
expected = (
|
||||||
('--keep-daily', '1'),
|
'--keep-daily',
|
||||||
('--match-archives', 'sh:Documents_{hostname}-{now}*'), # noqa: FS003
|
'1',
|
||||||
|
'--match-archives',
|
||||||
|
'sh:Documents_{hostname}-{now}*', # noqa: FS003
|
||||||
)
|
)
|
||||||
|
|
||||||
assert tuple(result) == expected
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
def test_make_prune_flags_with_prefix_without_borg_features_uses_glob_archives():
|
def test_make_prune_flags_with_prefix_without_borg_features_uses_glob_archives():
|
||||||
|
@ -53,37 +55,38 @@ def test_make_prune_flags_with_prefix_without_borg_features_uses_glob_archives()
|
||||||
(('keep_daily', 1), ('prefix', 'Documents_{hostname}-{now}')) # noqa: FS003
|
(('keep_daily', 1), ('prefix', 'Documents_{hostname}-{now}')) # noqa: FS003
|
||||||
)
|
)
|
||||||
flexmock(module.feature).should_receive('available').and_return(False)
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
|
|
||||||
result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
|
result = module.make_prune_flags({}, retention_config, local_borg_version='1.2.3')
|
||||||
|
|
||||||
expected = (
|
expected = (
|
||||||
('--keep-daily', '1'),
|
'--keep-daily',
|
||||||
('--glob-archives', 'Documents_{hostname}-{now}*'), # noqa: FS003
|
'1',
|
||||||
|
'--glob-archives',
|
||||||
|
'Documents_{hostname}-{now}*', # noqa: FS003
|
||||||
)
|
)
|
||||||
|
|
||||||
assert tuple(result) == expected
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
def test_make_prune_flags_treats_empty_prefix_as_no_prefix():
|
def test_make_prune_flags_without_prefix_uses_archive_name_format_instead():
|
||||||
retention_config = OrderedDict((('keep_daily', 1), ('prefix', '')))
|
storage_config = {'archive_name_format': 'bar-{now}'} # noqa: FS003
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
|
||||||
|
|
||||||
result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
|
|
||||||
|
|
||||||
expected = (('--keep-daily', '1'),)
|
|
||||||
|
|
||||||
assert tuple(result) == expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_prune_flags_treats_none_prefix_as_no_prefix():
|
|
||||||
retention_config = OrderedDict((('keep_daily', 1), ('prefix', None)))
|
retention_config = OrderedDict((('keep_daily', 1), ('prefix', None)))
|
||||||
flexmock(module.feature).should_receive('available').and_return(True)
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
'bar-{now}', '1.2.3' # noqa: FS003
|
||||||
|
).and_return(('--match-archives', 'sh:bar-*'))
|
||||||
|
|
||||||
result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
|
result = module.make_prune_flags(storage_config, retention_config, local_borg_version='1.2.3')
|
||||||
|
|
||||||
expected = (('--keep-daily', '1'),)
|
expected = (
|
||||||
|
'--keep-daily',
|
||||||
|
'1',
|
||||||
|
'--match-archives',
|
||||||
|
'sh:bar-*', # noqa: FS003
|
||||||
|
)
|
||||||
|
|
||||||
assert tuple(result) == expected
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
PRUNE_COMMAND = ('borg', 'prune', '--keep-daily', '1', '--keep-weekly', '2', '--keep-monthly', '3')
|
PRUNE_COMMAND = ('borg', 'prune', '--keep-daily', '1', '--keep-weekly', '2', '--keep-monthly', '3')
|
||||||
|
|
|
@ -127,6 +127,9 @@ def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_parameter
|
||||||
def test_make_rlist_command_includes_log_info():
|
def test_make_rlist_command_includes_log_info():
|
||||||
insert_logging_mock(logging.INFO)
|
insert_logging_mock(logging.INFO)
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -143,6 +146,9 @@ def test_make_rlist_command_includes_log_info():
|
||||||
def test_make_rlist_command_includes_json_but_not_info():
|
def test_make_rlist_command_includes_json_but_not_info():
|
||||||
insert_logging_mock(logging.INFO)
|
insert_logging_mock(logging.INFO)
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -159,6 +165,9 @@ def test_make_rlist_command_includes_json_but_not_info():
|
||||||
def test_make_rlist_command_includes_log_debug():
|
def test_make_rlist_command_includes_log_debug():
|
||||||
insert_logging_mock(logging.DEBUG)
|
insert_logging_mock(logging.DEBUG)
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -175,6 +184,9 @@ def test_make_rlist_command_includes_log_debug():
|
||||||
def test_make_rlist_command_includes_json_but_not_debug():
|
def test_make_rlist_command_includes_json_but_not_debug():
|
||||||
insert_logging_mock(logging.DEBUG)
|
insert_logging_mock(logging.DEBUG)
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -190,6 +202,9 @@ def test_make_rlist_command_includes_json_but_not_debug():
|
||||||
|
|
||||||
def test_make_rlist_command_includes_json():
|
def test_make_rlist_command_includes_json():
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -207,6 +222,9 @@ def test_make_rlist_command_includes_lock_wait():
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(
|
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(
|
||||||
('--lock-wait', '5')
|
('--lock-wait', '5')
|
||||||
).and_return(())
|
).and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -222,6 +240,9 @@ def test_make_rlist_command_includes_lock_wait():
|
||||||
|
|
||||||
def test_make_rlist_command_includes_local_path():
|
def test_make_rlist_command_includes_local_path():
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -240,6 +261,9 @@ def test_make_rlist_command_includes_remote_path():
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(
|
flexmock(module.flags).should_receive('make_flags').and_return(
|
||||||
('--remote-path', 'borg2')
|
('--remote-path', 'borg2')
|
||||||
).and_return(()).and_return(())
|
).and_return(()).and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -258,6 +282,9 @@ def test_make_rlist_command_transforms_prefix_into_match_archives():
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(()).and_return(
|
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(()).and_return(
|
||||||
('--match-archives', 'sh:foo*')
|
('--match-archives', 'sh:foo*')
|
||||||
)
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -271,8 +298,47 @@ def test_make_rlist_command_transforms_prefix_into_match_archives():
|
||||||
assert command == ('borg', 'list', '--match-archives', 'sh:foo*', 'repo')
|
assert command == ('borg', 'list', '--match-archives', 'sh:foo*', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_prefers_prefix_over_archive_name_format():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(()).and_return(
|
||||||
|
('--match-archives', 'sh:foo*')
|
||||||
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').never()
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository_path='repo',
|
||||||
|
storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix='foo'),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--match-archives', 'sh:foo*', 'repo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_rlist_command_transforms_archive_name_format_into_match_archives():
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
'bar-{now}', '1.2.3' # noqa: FS003
|
||||||
|
).and_return(('--match-archives', 'sh:bar-*'))
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
command = module.make_rlist_command(
|
||||||
|
repository_path='repo',
|
||||||
|
storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix=None),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert command == ('borg', 'list', '--match-archives', 'sh:bar-*', 'repo')
|
||||||
|
|
||||||
|
|
||||||
def test_make_rlist_command_includes_short():
|
def test_make_rlist_command_includes_short():
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--short',))
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--short',))
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
|
||||||
|
@ -301,6 +367,9 @@ def test_make_rlist_command_includes_short():
|
||||||
)
|
)
|
||||||
def test_make_rlist_command_includes_additional_flags(argument_name):
|
def test_make_rlist_command_includes_additional_flags(argument_name):
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
None, '1.2.3'
|
||||||
|
).and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
||||||
(f"--{argument_name.replace('_', '-')}", 'value')
|
(f"--{argument_name.replace('_', '-')}", 'value')
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,7 @@ def test_transfer_archives_calls_borg_with_flags():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -41,6 +42,7 @@ def test_transfer_archives_with_dry_run_calls_borg_with_dry_run_flag():
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args('dry-run', True).and_return(
|
flexmock(module.flags).should_receive('make_flags').with_args('dry-run', True).and_return(
|
||||||
('--dry-run',)
|
('--dry-run',)
|
||||||
)
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -67,6 +69,7 @@ def test_transfer_archives_with_log_info_calls_borg_with_info_flag():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -93,6 +96,7 @@ def test_transfer_archives_with_log_debug_calls_borg_with_debug_flag():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -123,6 +127,7 @@ def test_transfer_archives_with_archive_calls_borg_with_match_archives_flag():
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args(
|
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||||
'match-archives', 'archive'
|
'match-archives', 'archive'
|
||||||
).and_return(('--match-archives', 'archive'))
|
).and_return(('--match-archives', 'archive'))
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -137,7 +142,7 @@ def test_transfer_archives_with_archive_calls_borg_with_match_archives_flag():
|
||||||
module.transfer_archives(
|
module.transfer_archives(
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
repository_path='repo',
|
repository_path='repo',
|
||||||
storage_config={},
|
storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
|
||||||
local_borg_version='2.3.4',
|
local_borg_version='2.3.4',
|
||||||
transfer_arguments=flexmock(
|
transfer_arguments=flexmock(
|
||||||
archive='archive', progress=None, match_archives=None, source_repository=None
|
archive='archive', progress=None, match_archives=None, source_repository=None
|
||||||
|
@ -152,6 +157,7 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args(
|
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||||
'match-archives', 'sh:foo*'
|
'match-archives', 'sh:foo*'
|
||||||
).and_return(('--match-archives', 'sh:foo*'))
|
).and_return(('--match-archives', 'sh:foo*'))
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -166,7 +172,7 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl
|
||||||
module.transfer_archives(
|
module.transfer_archives(
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
repository_path='repo',
|
repository_path='repo',
|
||||||
storage_config={},
|
storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
|
||||||
local_borg_version='2.3.4',
|
local_borg_version='2.3.4',
|
||||||
transfer_arguments=flexmock(
|
transfer_arguments=flexmock(
|
||||||
archive=None, progress=None, match_archives='sh:foo*', source_repository=None
|
archive=None, progress=None, match_archives='sh:foo*', source_repository=None
|
||||||
|
@ -174,10 +180,40 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_transfer_archives_with_archive_name_format_calls_borg_with_match_archives_flag():
|
||||||
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').with_args(
|
||||||
|
'bar-{now}', '2.3.4' # noqa: FS003
|
||||||
|
).and_return(('--match-archives', 'sh:bar-*'))
|
||||||
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'transfer', '--match-archives', 'sh:bar-*', '--repo', 'repo'),
|
||||||
|
output_log_level=module.borgmatic.logger.ANSWER,
|
||||||
|
output_file=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
module.transfer_archives(
|
||||||
|
dry_run=False,
|
||||||
|
repository_path='repo',
|
||||||
|
storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003
|
||||||
|
local_borg_version='2.3.4',
|
||||||
|
transfer_arguments=flexmock(
|
||||||
|
archive=None, progress=None, match_archives=None, source_repository=None
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_transfer_archives_with_local_path_calls_borg_via_local_path():
|
def test_transfer_archives_with_local_path_calls_borg_via_local_path():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -208,6 +244,7 @@ def test_transfer_archives_with_remote_path_calls_borg_with_remote_path_flags():
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args(
|
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||||
'remote-path', 'borg2'
|
'remote-path', 'borg2'
|
||||||
).and_return(('--remote-path', 'borg2'))
|
).and_return(('--remote-path', 'borg2'))
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -238,6 +275,7 @@ def test_transfer_archives_with_lock_wait_calls_borg_with_lock_wait_flags():
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args('lock-wait', 5).and_return(
|
flexmock(module.flags).should_receive('make_flags').with_args('lock-wait', 5).and_return(
|
||||||
('--lock-wait', '5')
|
('--lock-wait', '5')
|
||||||
)
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
storage_config = {'lock_wait': 5}
|
storage_config = {'lock_wait': 5}
|
||||||
|
@ -265,6 +303,7 @@ def test_transfer_archives_with_progress_calls_borg_with_progress_flag():
|
||||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
@ -293,6 +332,7 @@ def test_transfer_archives_passes_through_arguments_to_borg(argument_name):
|
||||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||||
flag_name = f"--{argument_name.replace('_', ' ')}"
|
flag_name = f"--{argument_name.replace('_', ' ')}"
|
||||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
||||||
(flag_name, 'value')
|
(flag_name, 'value')
|
||||||
)
|
)
|
||||||
|
@ -327,6 +367,7 @@ def test_transfer_archives_with_source_repository_calls_borg_with_other_repo_fla
|
||||||
flexmock(module.flags).should_receive('make_flags').with_args('other-repo', 'other').and_return(
|
flexmock(module.flags).should_receive('make_flags').with_args('other-repo', 'other').and_return(
|
||||||
('--other-repo', 'other')
|
('--other-repo', 'other')
|
||||||
)
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
|
|
@ -37,7 +37,7 @@ def test_validation_error_string_contains_errors():
|
||||||
assert 'uh oh' in result
|
assert 'uh oh' in result
|
||||||
|
|
||||||
|
|
||||||
def test_apply_locical_validation_raises_if_unknown_repository_in_check_repositories():
|
def test_apply_logical_validation_raises_if_unknown_repository_in_check_repositories():
|
||||||
flexmock(module).format_json_error = lambda error: error.message
|
flexmock(module).format_json_error = lambda error: error.message
|
||||||
|
|
||||||
with pytest.raises(module.Validation_error):
|
with pytest.raises(module.Validation_error):
|
||||||
|
@ -51,17 +51,33 @@ def test_apply_locical_validation_raises_if_unknown_repository_in_check_reposito
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_apply_locical_validation_does_not_raise_if_known_repository_in_check_repositories():
|
def test_apply_logical_validation_does_not_raise_if_known_repository_path_in_check_repositories():
|
||||||
module.apply_logical_validation(
|
module.apply_logical_validation(
|
||||||
'config.yaml',
|
'config.yaml',
|
||||||
{
|
{
|
||||||
'location': {'repositories': ['repo.borg', 'other.borg']},
|
'location': {'repositories': [{'path': 'repo.borg'}, {'path': 'other.borg'}]},
|
||||||
'retention': {'keep_secondly': 1000},
|
'retention': {'keep_secondly': 1000},
|
||||||
'consistency': {'check_repositories': ['repo.borg']},
|
'consistency': {'check_repositories': ['repo.borg']},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_logical_validation_does_not_raise_if_known_repository_label_in_check_repositories():
|
||||||
|
module.apply_logical_validation(
|
||||||
|
'config.yaml',
|
||||||
|
{
|
||||||
|
'location': {
|
||||||
|
'repositories': [
|
||||||
|
{'path': 'repo.borg', 'label': 'my_repo'},
|
||||||
|
{'path': 'other.borg', 'label': 'other_repo'},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'retention': {'keep_secondly': 1000},
|
||||||
|
'consistency': {'check_repositories': ['my_repo']},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_apply_logical_validation_does_not_raise_if_archive_name_format_and_prefix_present():
|
def test_apply_logical_validation_does_not_raise_if_archive_name_format_and_prefix_present():
|
||||||
module.apply_logical_validation(
|
module.apply_logical_validation(
|
||||||
'config.yaml',
|
'config.yaml',
|
||||||
|
|
Loading…
Reference in a new issue