Compare commits

...
5 Commits
20 changed files with 234 additions and 133 deletions
+4
View File
@@ -28,4 +28,8 @@ Use `sudo borg --version`
Use `python3 --version`
**Database version (if applicable):** [version here]
Use `psql --version` or `mysql --version` on client and server.
**operating system and version:** [OS here]
+1 -1
View File
@@ -11,4 +11,4 @@ Robin `ypid` Schneider: Support additional options of Borg and add validate-borg
Scott Squires: Custom archive names
Thomas LÉVEIL: Support for a keep_minutely prune option. Support for the --json option
Any many others! See the output of "git log".
And many others! See the output of "git log".
+7
View File
@@ -1,3 +1,10 @@
1.4.10
* #246: Fix for "borgmatic restore" showing success and incorrectly extracting archive files, even
when no databases are configured to restore. As this can overwrite files from the archive and
lead to data loss, please upgrade to get the fix before using "borgmatic restore".
* Reopen the file given by "--log-file" flag if an external program rotates the log file while
borgmatic is running.
1.4.9
* #228: Database dump hooks for MySQL/MariaDB, so you can easily dump your databases before backups
run.
+24 -26
View File
@@ -18,7 +18,7 @@ from borgmatic.borg import list as borg_list
from borgmatic.borg import prune as borg_prune
from borgmatic.commands.arguments import parse_arguments
from borgmatic.config import checks, collect, convert, validate
from borgmatic.hooks import command, cronhub, cronitor, dispatch, dump, healthchecks
from borgmatic.hooks import command, dispatch, dump, monitor
from borgmatic.logger import configure_logging, should_do_markup
from borgmatic.signals import configure_signals
from borgmatic.verbosity import verbosity_to_log_level
@@ -53,14 +53,13 @@ def run_configuration(config_filename, config, arguments):
if 'create' in arguments:
try:
healthchecks.ping_healthchecks(
hooks.get('healthchecks'), config_filename, global_arguments.dry_run, 'start'
)
cronitor.ping_cronitor(
hooks.get('cronitor'), config_filename, global_arguments.dry_run, 'run'
)
cronhub.ping_cronhub(
hooks.get('cronhub'), config_filename, global_arguments.dry_run, 'start'
dispatch.call_hooks(
'ping_monitor',
hooks,
config_filename,
monitor.MONITOR_HOOK_NAMES,
monitor.State.START,
global_arguments.dry_run,
)
command.execute_hook(
hooks.get('before_backup'),
@@ -119,14 +118,13 @@ def run_configuration(config_filename, config, arguments):
'post-backup',
global_arguments.dry_run,
)
healthchecks.ping_healthchecks(
hooks.get('healthchecks'), config_filename, global_arguments.dry_run
)
cronitor.ping_cronitor(
hooks.get('cronitor'), config_filename, global_arguments.dry_run, 'complete'
)
cronhub.ping_cronhub(
hooks.get('cronhub'), config_filename, global_arguments.dry_run, 'finish'
dispatch.call_hooks(
'ping_monitor',
hooks,
config_filename,
monitor.MONITOR_HOOK_NAMES,
monitor.State.FINISH,
global_arguments.dry_run,
)
except (OSError, CalledProcessError) as error:
encountered_error = error
@@ -146,14 +144,13 @@ def run_configuration(config_filename, config, arguments):
error=encountered_error,
output=getattr(encountered_error, 'output', ''),
)
healthchecks.ping_healthchecks(
hooks.get('healthchecks'), config_filename, global_arguments.dry_run, 'fail'
)
cronitor.ping_cronitor(
hooks.get('cronitor'), config_filename, global_arguments.dry_run, 'fail'
)
cronhub.ping_cronhub(
hooks.get('cronhub'), config_filename, global_arguments.dry_run, 'fail'
dispatch.call_hooks(
'ping_monitor',
hooks,
config_filename,
monitor.MONITOR_HOOK_NAMES,
monitor.State.FAIL,
global_arguments.dry_run,
)
except (OSError, CalledProcessError) as error:
yield from make_error_log_records(
@@ -269,12 +266,13 @@ def run_actions(
dump.DATABASE_HOOK_NAMES,
restore_names,
)
borg_extract.extract_archive(
global_arguments.dry_run,
repository,
arguments['restore'].archive,
dump.convert_glob_patterns_to_borg_patterns(
[pattern for patterns in dump_patterns.values() for pattern in patterns]
dump.flatten_dump_patterns(dump_patterns, restore_names)
),
location,
storage,
+14 -8
View File
@@ -2,23 +2,29 @@ import logging
import requests
from borgmatic.hooks import monitor
logger = logging.getLogger(__name__)
MONITOR_STATE_TO_CRONHUB = {
monitor.State.START: 'start',
monitor.State.FINISH: 'finish',
monitor.State.FAIL: 'fail',
}
def ping_cronhub(ping_url, config_filename, dry_run, state):
def ping_monitor(ping_url, config_filename, state, dry_run):
'''
Ping the given Cronhub URL, substituting in the state string. Use the given configuration
Ping the given Cronhub URL, modified with the monitor.State. Use the given configuration
filename in any log entries. If this is a dry run, then don't actually ping anything.
'''
if not ping_url:
logger.debug('{}: No Cronhub hook set'.format(config_filename))
return
dry_run_label = ' (dry run; not actually pinging)' if dry_run else ''
formatted_state = '/{}/'.format(state)
formatted_state = '/{}/'.format(MONITOR_STATE_TO_CRONHUB[state])
ping_url = ping_url.replace('/start/', formatted_state).replace('/ping/', formatted_state)
logger.info('{}: Pinging Cronhub {}{}'.format(config_filename, state, dry_run_label))
logger.info(
'{}: Pinging Cronhub {}{}'.format(config_filename, state.name.lower(), dry_run_label)
)
logger.debug('{}: Using Cronhub ping URL {}'.format(config_filename, ping_url))
if not dry_run:
+16 -10
View File
@@ -2,22 +2,28 @@ import logging
import requests
from borgmatic.hooks import monitor
logger = logging.getLogger(__name__)
MONITOR_STATE_TO_CRONITOR = {
monitor.State.START: 'run',
monitor.State.FINISH: 'complete',
monitor.State.FAIL: 'fail',
}
def ping_cronitor(ping_url, config_filename, dry_run, append):
'''
Ping the given Cronitor URL, appending the append string. Use the given configuration filename
in any log entries. If this is a dry run, then don't actually ping anything.
'''
if not ping_url:
logger.debug('{}: No Cronitor hook set'.format(config_filename))
return
def ping_monitor(ping_url, config_filename, state, dry_run):
'''
Ping the given Cronitor URL, modified with the monitor.State. Use the given configuration
filename in any log entries. If this is a dry run, then don't actually ping anything.
'''
dry_run_label = ' (dry run; not actually pinging)' if dry_run else ''
ping_url = '{}/{}'.format(ping_url, append)
ping_url = '{}/{}'.format(ping_url, MONITOR_STATE_TO_CRONITOR[state])
logger.info('{}: Pinging Cronitor {}{}'.format(config_filename, append, dry_run_label))
logger.info(
'{}: Pinging Cronitor {}{}'.format(config_filename, state.name.lower(), dry_run_label)
)
logger.debug('{}: Using Cronitor ping URL {}'.format(config_filename, ping_url))
if not dry_run:
+8 -2
View File
@@ -1,10 +1,16 @@
import logging
from borgmatic.hooks import mysql, postgresql
from borgmatic.hooks import cronhub, cronitor, healthchecks, mysql, postgresql
logger = logging.getLogger(__name__)
HOOK_NAME_TO_MODULE = {'postgresql_databases': postgresql, 'mysql_databases': mysql}
HOOK_NAME_TO_MODULE = {
'healthchecks': healthchecks,
'cronitor': cronitor,
'cronhub': cronhub,
'postgresql_databases': postgresql,
'mysql_databases': mysql,
}
def call_hook(function_name, hooks, log_prefix, hook_name, *args, **kwargs):
+25 -1
View File
@@ -20,6 +20,26 @@ def make_database_dump_filename(dump_path, name, hostname=None):
return os.path.join(os.path.expanduser(dump_path), hostname or 'localhost', name)
def flatten_dump_patterns(dump_patterns, names):
'''
Given a dict from a database hook name to glob patterns matching the dumps for the named
databases, flatten out all the glob patterns into a single sequence, and return it.
Raise ValueError if there are no resulting glob patterns, which indicates that databases are not
configured in borgmatic's configuration.
'''
flattened = [pattern for patterns in dump_patterns.values() for pattern in patterns]
if not flattened:
raise ValueError(
'Cannot restore database(s) {} missing from borgmatic\'s configuration'.format(
', '.join(names) or '"all"'
)
)
return flattened
def remove_database_dumps(dump_path, databases, database_type_name, log_prefix, dry_run):
'''
Remove the database dumps for the given databases in the dump directory path. The databases are
@@ -109,7 +129,6 @@ def get_per_hook_database_configurations(hooks, names, dump_patterns):
Raise ValueError if one of the database names cannot be matched to a database in borgmatic's
database configuration.
'''
# TODO: Need to filter names by database type? Maybe take a database --type argument to disambiguate.
hook_databases = {
hook_name: list(
get_database_configurations(
@@ -122,6 +141,11 @@ def get_per_hook_database_configurations(hooks, names, dump_patterns):
}
if not names or 'all' in names:
if not any(hook_databases.values()):
raise ValueError(
'Cannot restore database "all", as there are no database dumps in the archive'
)
return hook_databases
found_names = {
+14 -11
View File
@@ -2,19 +2,23 @@ import logging
import requests
from borgmatic.hooks import monitor
logger = logging.getLogger(__name__)
MONITOR_STATE_TO_HEALTHCHECKS = {
monitor.State.START: 'start',
monitor.State.FINISH: None, # Healthchecks doesn't append to the URL for the finished state.
monitor.State.FAIL: 'fail',
}
def ping_healthchecks(ping_url_or_uuid, config_filename, dry_run, append=None):
def ping_monitor(ping_url_or_uuid, config_filename, state, dry_run):
'''
Ping the given Healthchecks URL or UUID, appending the append string if any. Use the given
Ping the given Healthchecks URL or UUID, modified with the monitor.State. Use the given
configuration filename in any log entries. If this is a dry run, then don't actually ping
anything.
'''
if not ping_url_or_uuid:
logger.debug('{}: No Healthchecks hook set'.format(config_filename))
return
ping_url = (
ping_url_or_uuid
if ping_url_or_uuid.startswith('http')
@@ -22,13 +26,12 @@ def ping_healthchecks(ping_url_or_uuid, config_filename, dry_run, append=None):
)
dry_run_label = ' (dry run; not actually pinging)' if dry_run else ''
if append:
ping_url = '{}/{}'.format(ping_url, append)
healthchecks_state = MONITOR_STATE_TO_HEALTHCHECKS.get(state)
if healthchecks_state:
ping_url = '{}/{}'.format(ping_url, healthchecks_state)
logger.info(
'{}: Pinging Healthchecks{}{}'.format(
config_filename, ' ' + append if append else '', dry_run_label
)
'{}: Pinging Healthchecks {}{}'.format(config_filename, state.name.lower(), dry_run_label)
)
logger.debug('{}: Using Healthchecks ping URL {}'.format(config_filename, ping_url))
+9
View File
@@ -0,0 +1,9 @@
from enum import Enum
MONITOR_HOOK_NAMES = ('healthchecks', 'cronitor', 'cronhub')
class State(Enum):
START = 1
FINISH = 2
FAIL = 3
+1 -1
View File
@@ -104,7 +104,7 @@ def configure_logging(
syslog_handler.setLevel(syslog_log_level)
handlers = (console_handler, syslog_handler)
elif log_file:
file_handler = logging.FileHandler(log_file)
file_handler = logging.handlers.WatchedFileHandler(log_file)
file_handler.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s: %(message)s'))
file_handler.setLevel(log_file_log_level)
handlers = (console_handler, file_handler)
+15 -14
View File
@@ -70,6 +70,21 @@ Or to increase syslog logging to include debug spew:
borgmatic --syslog-verbosity 2
```
### Rate limiting
If you are using rsyslog or systemd's journal, be aware that by default they
both throttle the rate at which logging occurs. So you may need to change
either [the global rate
limit](https://www.rootusers.com/how-to-change-log-rate-limiting-in-linux/) or
[the per-service rate
limit](https://www.freedesktop.org/software/systemd/man/journald.conf.html#RateLimitIntervalSec=)
if you're finding that borgmatic logs are missing.
Note that the [sample borgmatic systemd service
file](https://torsion.org/borgmatic/docs/how-to/set-up-backups/#systemd)
already has this rate limit disabled for systemd's journal.
### Logging to file
If you don't want to use syslog, and you'd rather borgmatic log to a plain
@@ -84,20 +99,6 @@ the log file so it doesn't grow too large. Also, there is a
`--log-file-verbosity` flag to customize the log file's log level.
### systemd journal
If your local syslog daemon is systemd's journal, be aware that journald by
default throttles the rate at which a particular program can log. So you may
need to [change the journald rate
limit](https://www.freedesktop.org/software/systemd/man/journald.conf.html#RateLimitIntervalSec=)
in `/etc/systemd/journald.conf` if you're finding that borgmatic journald logs
are missing.
Note that the [sample borgmatic systemd service
file](https://torsion.org/borgmatic/docs/how-to/set-up-backups/#systemd)
already has this rate limit disabled.
## Related documentation
* [Set up backups with borgmatic](https://torsion.org/borgmatic/docs/how-to/set-up-backups/)
+3 -3
View File
@@ -39,9 +39,9 @@ generate-borgmatic-config --source config.yaml --destination config-new.yaml
New options start as commented out, so you can edit the file and decide
whether you want to use each one.
There are a few caveats to this process, however. First, when generating the
new configuration file, `generate-borgmatic-config` replaces any comments
you've written in your original configuration file with the newest generated
There are a few caveats to this process. First, when generating the new
configuration file, `generate-borgmatic-config` replaces any comments you've
written in your original configuration file with the newest generated
comments. Second, the script adds back any options you had originally deleted,
although it does so with the options commented out. And finally, any YAML
includes you've used in the source configuration get flattened out into a
+1 -1
View File
@@ -1,6 +1,6 @@
from setuptools import find_packages, setup
VERSION = '1.4.9'
VERSION = '1.4.10'
setup(
+1 -10
View File
@@ -23,10 +23,7 @@ def test_run_configuration_runs_actions_for_each_repository():
def test_run_configuration_executes_hooks_for_create_action():
flexmock(module.borg_environment).should_receive('initialize')
flexmock(module.command).should_receive('execute_hook').twice()
flexmock(module.dispatch).should_receive('call_hooks').twice()
flexmock(module.healthchecks).should_receive('ping_healthchecks').twice()
flexmock(module.cronitor).should_receive('ping_cronitor').twice()
flexmock(module.cronhub).should_receive('ping_cronhub').twice()
flexmock(module.dispatch).should_receive('call_hooks').at_least().twice()
flexmock(module).should_receive('run_actions').and_return([])
config = {'location': {'repositories': ['foo']}}
arguments = {'global': flexmock(dry_run=False), 'create': flexmock()}
@@ -38,9 +35,6 @@ def test_run_configuration_logs_actions_error():
flexmock(module.borg_environment).should_receive('initialize')
flexmock(module.command).should_receive('execute_hook')
flexmock(module.dispatch).should_receive('call_hooks')
flexmock(module.healthchecks).should_receive('ping_healthchecks')
flexmock(module.cronitor).should_receive('ping_cronitor')
flexmock(module.cronhub).should_receive('ping_cronhub')
expected_results = [flexmock()]
flexmock(module).should_receive('make_error_log_records').and_return(expected_results)
flexmock(module).should_receive('run_actions').and_raise(OSError)
@@ -72,9 +66,6 @@ def test_run_configuration_logs_post_hook_error():
OSError
).and_return(None)
flexmock(module.dispatch).should_receive('call_hooks')
flexmock(module.healthchecks).should_receive('ping_healthchecks')
flexmock(module.cronitor).should_receive('ping_cronitor')
flexmock(module.cronhub).should_receive('ping_cronhub')
expected_results = [flexmock()]
flexmock(module).should_receive('make_error_log_records').and_return(expected_results)
flexmock(module).should_receive('run_actions').and_return([])
+19 -13
View File
@@ -3,30 +3,36 @@ from flexmock import flexmock
from borgmatic.hooks import cronhub as module
def test_ping_cronhub_hits_ping_url_with_start_state():
def test_ping_monitor_rewrites_ping_url_for_start_state():
ping_url = 'https://example.com/start/abcdef'
state = 'bork'
flexmock(module.requests).should_receive('get').with_args('https://example.com/bork/abcdef')
flexmock(module.requests).should_receive('get').with_args('https://example.com/start/abcdef')
module.ping_cronhub(ping_url, 'config.yaml', dry_run=False, state=state)
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.START, dry_run=False)
def test_ping_cronhub_hits_ping_url_with_ping_state():
def test_ping_monitor_rewrites_ping_url_and_state_for_start_state():
ping_url = 'https://example.com/ping/abcdef'
state = 'bork'
flexmock(module.requests).should_receive('get').with_args('https://example.com/bork/abcdef')
flexmock(module.requests).should_receive('get').with_args('https://example.com/start/abcdef')
module.ping_cronhub(ping_url, 'config.yaml', dry_run=False, state=state)
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.START, dry_run=False)
def test_ping_cronhub_without_ping_url_does_not_raise():
flexmock(module.requests).should_receive('get').never()
def test_ping_monitor_rewrites_ping_url_for_finish_state():
ping_url = 'https://example.com/start/abcdef'
flexmock(module.requests).should_receive('get').with_args('https://example.com/finish/abcdef')
module.ping_cronhub(ping_url=None, config_filename='config.yaml', dry_run=False, state='oops')
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.FINISH, dry_run=False)
def test_ping_cronhub_dry_run_does_not_hit_ping_url():
def test_ping_monitor_rewrites_ping_url_for_fail_state():
ping_url = 'https://example.com/start/abcdef'
flexmock(module.requests).should_receive('get').with_args('https://example.com/fail/abcdef')
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.FAIL, dry_run=False)
def test_ping_monitor_dry_run_does_not_hit_ping_url():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').never()
module.ping_cronhub(ping_url, 'config.yaml', dry_run=True, state='yay')
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.START, dry_run=True)
+16 -9
View File
@@ -3,22 +3,29 @@ from flexmock import flexmock
from borgmatic.hooks import cronitor as module
def test_ping_cronitor_hits_ping_url():
def test_ping_monitor_hits_ping_url_for_start_state():
ping_url = 'https://example.com'
append = 'failed-so-hard'
flexmock(module.requests).should_receive('get').with_args('{}/{}'.format(ping_url, append))
flexmock(module.requests).should_receive('get').with_args('{}/{}'.format(ping_url, 'run'))
module.ping_cronitor(ping_url, 'config.yaml', dry_run=False, append=append)
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.START, dry_run=False)
def test_ping_cronitor_without_ping_url_does_not_raise():
flexmock(module.requests).should_receive('get').never()
def test_ping_monitor_hits_ping_url_for_finish_state():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').with_args('{}/{}'.format(ping_url, 'complete'))
module.ping_cronitor(ping_url=None, config_filename='config.yaml', dry_run=False, append='oops')
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.FINISH, dry_run=False)
def test_ping_cronitor_dry_run_does_not_hit_ping_url():
def test_ping_monitor_hits_ping_url_for_fail_state():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').with_args('{}/{}'.format(ping_url, 'fail'))
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.FAIL, dry_run=False)
def test_ping_monitor_dry_run_does_not_hit_ping_url():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').never()
module.ping_cronitor(ping_url, 'config.yaml', dry_run=True, append='yay')
module.ping_monitor(ping_url, 'config.yaml', module.monitor.State.START, dry_run=True)
+33
View File
@@ -26,6 +26,27 @@ def test_make_database_dump_filename_with_invalid_name_raises():
module.make_database_dump_filename('databases', 'invalid/name')
def test_flatten_dump_patterns_produces_list_of_all_patterns():
dump_patterns = {'postgresql_databases': ['*/glob', 'glob/*'], 'mysql_databases': ['*/*/*']}
expected_patterns = dump_patterns['postgresql_databases'] + dump_patterns['mysql_databases']
assert module.flatten_dump_patterns(dump_patterns, ('bob',)) == expected_patterns
def test_flatten_dump_patterns_with_no_patterns_errors():
dump_patterns = {'postgresql_databases': [], 'mysql_databases': []}
with pytest.raises(ValueError):
assert module.flatten_dump_patterns(dump_patterns, ('bob',))
def test_flatten_dump_patterns_with_no_hooks_errors():
dump_patterns = {}
with pytest.raises(ValueError):
assert module.flatten_dump_patterns(dump_patterns, ('bob',))
def test_remove_database_dumps_removes_dump_for_each_database():
databases = [{'name': 'foo'}, {'name': 'bar'}]
flexmock(module).should_receive('make_database_dump_filename').and_return(
@@ -134,3 +155,15 @@ def test_get_per_hook_database_configurations_with_unknown_database_name_raises(
with pytest.raises(ValueError):
module.get_per_hook_database_configurations(hooks, names, dump_patterns)
def test_get_per_hook_database_configurations_with_all_and_no_archive_dumps_raises():
hooks = {'postgresql_databases': [flexmock()]}
names = ('foo', 'all')
dump_patterns = flexmock()
flexmock(module).should_receive('get_database_configurations').with_args(
hooks['postgresql_databases'], names
).and_return([])
with pytest.raises(ValueError):
module.get_per_hook_database_configurations(hooks, names, dump_patterns)
+17 -17
View File
@@ -3,38 +3,38 @@ from flexmock import flexmock
from borgmatic.hooks import healthchecks as module
def test_ping_healthchecks_hits_ping_url():
def test_ping_monitor_hits_ping_url_for_start_state():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').with_args('{}/{}'.format(ping_url, 'start'))
module.ping_monitor(ping_url, 'config.yaml', state=module.monitor.State.START, dry_run=False)
def test_ping_monitor_hits_ping_url_for_finish_state():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').with_args(ping_url)
module.ping_healthchecks(ping_url, 'config.yaml', dry_run=False)
module.ping_monitor(ping_url, 'config.yaml', state=module.monitor.State.FINISH, dry_run=False)
def test_ping_healthchecks_without_ping_url_does_not_raise():
flexmock(module.requests).should_receive('get').never()
def test_ping_monitor_hits_ping_url_for_fail_state():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').with_args('{}/{}'.format(ping_url, 'fail'))
module.ping_healthchecks(ping_url_or_uuid=None, config_filename='config.yaml', dry_run=False)
module.ping_monitor(ping_url, 'config.yaml', state=module.monitor.State.FAIL, dry_run=False)
def test_ping_healthchecks_with_ping_uuid_hits_corresponding_url():
def test_ping_monitor_with_ping_uuid_hits_corresponding_url():
ping_uuid = 'abcd-efgh-ijkl-mnop'
flexmock(module.requests).should_receive('get').with_args(
'https://hc-ping.com/{}'.format(ping_uuid)
)
module.ping_healthchecks(ping_uuid, 'config.yaml', dry_run=False)
module.ping_monitor(ping_uuid, 'config.yaml', state=module.monitor.State.FINISH, dry_run=False)
def test_ping_healthchecks_hits_ping_url_with_append():
ping_url = 'https://example.com'
append = 'failed-so-hard'
flexmock(module.requests).should_receive('get').with_args('{}/{}'.format(ping_url, append))
module.ping_healthchecks(ping_url, 'config.yaml', dry_run=False, append=append)
def test_ping_healthchecks_dry_run_does_not_hit_ping_url():
def test_ping_monitor_dry_run_does_not_hit_ping_url():
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('get').never()
module.ping_healthchecks(ping_url, 'config.yaml', dry_run=True)
module.ping_monitor(ping_url, 'config.yaml', state=module.monitor.State.START, dry_run=True)
+6 -6
View File
@@ -203,10 +203,10 @@ def test_configure_logging_to_logfile_instead_of_syslog():
)
flexmock(module.os.path).should_receive('exists').with_args('/dev/log').and_return(True)
flexmock(module.logging.handlers).should_receive('SysLogHandler').never()
file_handler = logging.FileHandler('/tmp/logfile')
flexmock(module.logging).should_receive('FileHandler').with_args('/tmp/logfile').and_return(
file_handler
).once()
file_handler = logging.handlers.WatchedFileHandler('/tmp/logfile')
flexmock(module.logging.handlers).should_receive('WatchedFileHandler').with_args(
'/tmp/logfile'
).and_return(file_handler).once()
module.configure_logging(
console_log_level=logging.INFO, log_file_log_level=logging.DEBUG, log_file='/tmp/logfile'
@@ -214,12 +214,12 @@ def test_configure_logging_to_logfile_instead_of_syslog():
def test_configure_logging_skips_logfile_if_argument_is_none():
# No FileHandler added if argument --log-file is None
# No WatchedFileHandler added if argument --log-file is None
flexmock(module).should_receive('interactive_console').and_return(False)
flexmock(module.logging).should_receive('basicConfig').with_args(
level=logging.INFO, handlers=tuple
)
flexmock(module.os.path).should_receive('exists').and_return(False)
flexmock(module.logging).should_receive('FileHandler').never()
flexmock(module.logging.handlers).should_receive('WatchedFileHandler').never()
module.configure_logging(console_log_level=logging.INFO, log_file=None)