WIP: Separate endpoint for each primary action for monitor hooks #660
|
@ -249,6 +249,12 @@ def make_parsers():
|
|||
action='store_true',
|
||||
help='Go through the motions, but do not actually write to any repositories',
|
||||
)
|
||||
global_group.add_argument(
|
||||
'--skip-monitoring',
|
||||
dest='skip_monitoring',
|
||||
action='store_true',
|
||||
help='Skip reporting any data to the configured monitoring services',
|
||||
)
|
||||
global_group.add_argument(
|
||||
'-nc', '--no-color', dest='no_color', action='store_true', help='Disable colored output'
|
||||
)
|
||||
|
|
|
@ -68,6 +68,10 @@ def run_configuration(config_filename, config, arguments):
|
|||
error_repository = ''
|
||||
using_primary_action = {'create', 'prune', 'compact', 'check'}.intersection(arguments)
|
||||
jetchirag marked this conversation as resolved
Outdated
|
||||
monitoring_log_level = verbosity_to_log_level(global_arguments.monitoring_verbosity)
|
||||
skip_monitoring = global_arguments.skip_monitoring
|
||||
jetchirag marked this conversation as resolved
Outdated
witten
commented
On the On the `isinstance()` call: Shouldn't they always be strings? Or is something else sneaking in there?
|
||||
action_names = [
|
||||
action for action in arguments.keys() if action != 'global'
|
||||
]
|
||||
monitoring_hooks_are_activated = using_primary_action and monitoring_log_level != DISABLED
|
||||
|
||||
try:
|
||||
|
@ -77,7 +81,7 @@ def run_configuration(config_filename, config, arguments):
|
|||
return
|
||||
|
||||
try:
|
||||
if monitoring_hooks_are_activated:
|
||||
if using_primary_action and not skip_monitoring and monitoring_hooks_are_activated:
|
||||
dispatch.call_hooks(
|
||||
'initialize_monitor',
|
||||
config,
|
||||
|
@ -87,15 +91,17 @@ def run_configuration(config_filename, config, arguments):
|
|||
global_arguments.dry_run,
|
||||
)
|
||||
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.START,
|
||||
monitoring_log_level,
|
||||
global_arguments.dry_run,
|
||||
)
|
||||
for action_name in action_names:
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.START,
|
||||
monitoring_log_level,
|
||||
witten
commented
I know we've going back and forth on the subject of looping over
I think that means with the actions loop in place and So, the question is what to do about this. One idea is to remove the above normalization code so that you can retain the prior behavior when I know we've going back and forth on the subject of looping over `ping_monitor` calls, but something occurs to me: Are there cases where this will ping the monitor multiple times even if it's only configured with a single `ping_url` option? I'm thinking of this code in `normalize.py`:
```
config['hooks']['cronitor'] = {
'create': cronitor['ping_url'],
'prune': cronitor['ping_url'],
'compact': cronitor['ping_url'],
'check': cronitor['ping_url'],
}
```
I think that means with the actions loop in place and `ping_url` set, Cronitor will get pinged *four* times for a standard borgmatic run. But shouldn't it ideally only get pinged *once* on start—unless the user explicitly configures ping endpoints for multiple actions?
So, the question is what to do about this. One idea is to remove the above normalization code so that you can retain the prior behavior when `ping_url` is set: Only ping *once* on start. Another idea is to drop support for `ping_url` entirely. There are probably other options as well. I'm open to discussion on this point of course! I didn't realize this would be such a thorny ticket.
jetchirag
commented
@witten I had this concern too since I started working on this. I was also wondering if someone wants to receive notification for a failed event in any of 4 actions, he will have to set the endpoints in each of them and same for future update. And suppose someone wants to get notified for failure in all of these actions, it will send alert 4 times if all of them fail, where probability of other act So what if we keep the ping_url but add a boolean configuration so user can select which action to receive notification on. I don't think people will use different cronitor endpoint for different actions of same job. This should still fulfil the problem raised in this PR's issue. It's been a while since I worked on this so I might be misunderstanding something here. So these are just the thoughts I gathered going over the code again. Let me know what you think. @witten I had this concern too since I started working on this. I was also wondering if someone wants to receive notification for a failed event in any of 4 actions, he will have to set the endpoints in each of them and same for future update.
And suppose someone wants to get notified for failure in all of these actions, it will send alert 4 times if all of them fail, where probability of other act
So what if we keep the ping_url but add a boolean configuration so user can select which action to receive notification on. I don't think people will use different cronitor endpoint for different actions of same job.
This should still fulfil the problem raised in this PR's issue.
It's been a while since I worked on this so I might be misunderstanding something here. So these are just the thoughts I gathered going over the code again. Let me know what you think.
witten
commented
It's also been a while since I've looked at this code! Could you maybe provide a configuration example to illustrate what you're thinking here? For instance, I'm unsure how an additional boolean configuration option would allow a user to select which borgmatic action to receive notifications on. I would think that any action with a Cronitor URL set would receive a notification. Or is the distinction you're drawing that, for a given action, URLs might only be notified for some of begin/start/fail and not all three?
Looking at #518, I think a common case is probably where the user wants one URL for, say, the For the current (released borgmatic) use case of pinging Cronitor only once for begin/start/fail when the action is create, prune, compact, or check.. What do you think of including some logic such that if a URL is specified for multiple different actions (whether explicitly.. or implicitly via I've given no thought to how that might be implemented, but such de-duplication seems nice from a user perspective—and it lines up with the currently released behavior. Let me know though if this doesn't sound feasible or desirable. It's also been a while since I've looked at this code! Could you maybe provide a configuration example to illustrate what you're thinking here? For instance, I'm unsure how an additional boolean configuration option would allow a user to select which borgmatic action to receive notifications on. I would think that any action with a Cronitor URL set would receive a notification. Or is the distinction you're drawing that, for a given action, URLs might only be notified for some of begin/start/fail and not all three?
> I don't think people will use different cronitor endpoint for different actions of same job.
Looking at #518, I think a common case *is* probably where the user wants one URL for, say, the `create` action and a completely different URL if any for, say, the `check` action. (See #366 as well.) In that case it wouldn't be a problem that each such URL would get pinged once upon failure, as each action is hitting a different Cronitor endpoint.
For the current (released borgmatic) use case of pinging Cronitor only once for begin/start/fail when the action is create, prune, compact, or check.. What do you think of including some logic such that if a URL is specified for multiple different actions (whether explicitly.. or implicitly via `ping_url`), then borgmatic is smart enough to only ping Cronitor once before/after all the actions and once on failure.
I've given no thought to how that might be implemented, but such de-duplication seems nice from a user perspective—and it lines up with the currently released behavior. Let me know though if this doesn't sound feasible or desirable.
jetchirag
commented
It makes sense to include logic to remove duplicate endpoints. I'll add that. I've fixed the latest merge conflicts and will start working on the rest of suggestions. Development might still be slow unfortunately since classes are starting but I'll keep at it. Since merge conflicts are fixed, I can solve the rest in small pieces. Thank you for the help and patience! It makes sense to include logic to remove duplicate endpoints. I'll add that.
I've fixed the latest merge conflicts and will start working on the rest of suggestions. Development might still be slow unfortunately since classes are starting but I'll keep at it. Since merge conflicts are fixed, I can solve the rest in small pieces.
Thank you for the help and patience!
|
||||
global_arguments.dry_run,
|
||||
action_name,
|
||||
)
|
||||
except (OSError, CalledProcessError) as error:
|
||||
if command.considered_soft_failure(config_filename, error):
|
||||
return
|
||||
|
@ -160,17 +166,19 @@ def run_configuration(config_filename, config, arguments):
|
|||
error_repository = repository['path']
|
||||
|
||||
try:
|
||||
if monitoring_hooks_are_activated:
|
||||
if using_primary_action and not skip_monitoring and monitoring_hooks_are_activated:
|
||||
# send logs irrespective of error
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.LOG,
|
||||
monitoring_log_level,
|
||||
global_arguments.dry_run,
|
||||
)
|
||||
for action_name in action_names:
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.LOG,
|
||||
monitoring_log_level,
|
||||
global_arguments.dry_run,
|
||||
action_name,
|
||||
)
|
||||
except (OSError, CalledProcessError) as error:
|
||||
if command.considered_soft_failure(config_filename, error):
|
||||
return
|
||||
|
@ -180,16 +188,18 @@ def run_configuration(config_filename, config, arguments):
|
|||
|
||||
if not encountered_error:
|
||||
try:
|
||||
if monitoring_hooks_are_activated:
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.FINISH,
|
||||
monitoring_log_level,
|
||||
global_arguments.dry_run,
|
||||
)
|
||||
if using_primary_action and not skip_monitoring and monitoring_hooks_are_activated:
|
||||
for action_name in action_names:
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.FINISH,
|
||||
monitoring_log_level,
|
||||
global_arguments.dry_run,
|
||||
action_name,
|
||||
)
|
||||
dispatch.call_hooks(
|
||||
'destroy_monitor',
|
||||
config,
|
||||
|
@ -217,15 +227,17 @@ def run_configuration(config_filename, config, arguments):
|
|||
error=encountered_error,
|
||||
output=getattr(encountered_error, 'output', ''),
|
||||
)
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.FAIL,
|
||||
monitoring_log_level,
|
||||
global_arguments.dry_run,
|
||||
)
|
||||
for action_name in action_names:
|
||||
dispatch.call_hooks(
|
||||
'ping_monitor',
|
||||
config,
|
||||
config_filename,
|
||||
monitor.MONITOR_HOOK_NAMES,
|
||||
monitor.State.FAIL,
|
||||
monitoring_log_level,
|
||||
global_arguments.dry_run,
|
||||
action_name,
|
||||
)
|
||||
dispatch.call_hooks(
|
||||
'destroy_monitor',
|
||||
config,
|
||||
|
|
|
@ -104,6 +104,13 @@ def normalize(config_filename, config):
|
|||
)
|
||||
)
|
||||
config['cronitor'] = {'ping_url': cronitor}
|
||||
if isinstance(cronitor, dict) and 'ping_url' in cronitor:
|
||||
config['hooks']['cronitor'] = {
|
||||
'create': cronitor['ping_url'],
|
||||
'prune': cronitor['ping_url'],
|
||||
'compact': cronitor['ping_url'],
|
||||
'check': cronitor['ping_url'],
|
||||
}
|
||||
|
||||
pagerduty = config.get('pagerduty')
|
||||
if isinstance(pagerduty, str):
|
||||
|
|
|
@ -1151,13 +1151,49 @@ properties:
|
|||
example: incoming_envelope
|
||||
fail:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
title:
|
||||
create:
|
||||
type: string
|
||||
description: |
|
||||
The title of the message.
|
||||
example: Ping!
|
||||
message:
|
||||
Cronitor ping URL to notify when a backup
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
prune:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a prune action
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
compact:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a compact action
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
check:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a check action
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
ping_url:
|
||||
type: string
|
||||
description: |
|
||||
If this is set, other properties will be ignored
|
||||
and replaced by this value.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
description: |
|
||||
Configuration for a monitoring integration with Cronitor.
|
||||
Create an account at https://cronitor.io if you'd
|
||||
like to use this service. See borgmatic monitoring
|
||||
documentation for details.
|
||||
pagerduty:
|
||||
type: object
|
||||
required: ['integration_key']
|
||||
additionalProperties: false
|
||||
properties:
|
||||
integration_key:
|
||||
type: string
|
||||
description: |
|
||||
The message body to publish.
|
||||
|
@ -1242,19 +1278,43 @@ properties:
|
|||
documentation for details.
|
||||
cronitor:
|
||||
type: object
|
||||
required: ['ping_url']
|
||||
additionalProperties: false
|
||||
properties:
|
||||
create:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a backup
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
prune:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a prune action
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
compact:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a compact action
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
check:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a check action
|
||||
begins, ends, or errors.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
ping_url:
|
||||
type: string
|
||||
description: |
|
||||
Cronitor ping URL to notify when a backup begins,
|
||||
ends, or errors.
|
||||
If this is set, other properties will be ignored
|
||||
and replaced by this value.
|
||||
example: https://cronitor.link/d3x0c1
|
||||
description: |
|
||||
Configuration for a monitoring integration with Cronitor. Create an
|
||||
account at https://cronitor.io if you'd like to use this service.
|
||||
See borgmatic monitoring documentation for details.
|
||||
Configuration for a monitoring integration with Cronitor.
|
||||
Create an account at https://cronitor.io if you'd
|
||||
like to use this service. See borgmatic monitoring
|
||||
documentation for details.
|
||||
pagerduty:
|
||||
type: object
|
||||
required: ['integration_key']
|
||||
|
|
|
@ -22,7 +22,7 @@ def initialize_monitor(
|
|||
pass
|
||||
|
||||
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run):
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run, action_name):
|
||||
jetchirag marked this conversation as resolved
Outdated
witten
commented
To support the multiple actions thing mentioned above, a couple of options I can think of:
To support the multiple actions thing mentioned above, a couple of options I can think of:
* Change this to take multiple action names and internally loop accordingly.
* Or, call `ping_monitor()` in a loop over the action names.
jetchirag
commented
I decided to go with calling ping_monitor in a loop. I decided to go with calling ping_monitor in a loop.
witten
commented
Sounds good. Please let me know when this is ready for me to have another look! Sounds good. Please let me know when this is ready for me to have another look!
jetchirag
commented
I think it's ready for a review. Only tests should be missing. I think it's ready for a review. Only tests should be missing.
|
||||
'''
|
||||
Ping the configured 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.
|
||||
|
|
|
@ -22,7 +22,7 @@ def initialize_monitor(
|
|||
pass
|
||||
|
||||
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run):
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run, action_name):
|
||||
'''
|
||||
Ping the configured 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.
|
||||
|
@ -34,7 +34,13 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
|
|||
return
|
||||
|
||||
dry_run_label = ' (dry run; not actually pinging)' if dry_run else ''
|
||||
ping_url = f"{hook_config['ping_url']}/{MONITOR_STATE_TO_CRONITOR[state]}"
|
||||
try:
|
||||
ping_url = f"{hook_config[action_name]}/{MONITOR_STATE_TO_CRONITOR[state]}"
|
||||
except KeyError:
|
||||
jetchirag marked this conversation as resolved
witten
commented
Nice, succinct way to skip unconfigured actions. You could optionally Nice, succinct way to skip unconfigured actions. You could optionally `logger.debug()` in the `except` so that it's clear what's being skipped and why.
|
||||
logger.debug(
|
||||
jetchirag marked this conversation as resolved
Outdated
diivi
commented
Missed a debug log here 😄 Missed a debug log here 😄
jetchirag
commented
Thanks! :) Thanks! :)
|
||||
f'{config_filename}: Skipping Cronitor {state.name.lower()} ping due to unconfigured action: {action_name}'
|
||||
)
|
||||
return
|
||||
|
||||
logger.info(f'{config_filename}: Pinging Cronitor {state.name.lower()}{dry_run_label}')
|
||||
logger.debug(f'{config_filename}: Using Cronitor ping URL {ping_url}')
|
||||
|
|
|
@ -90,7 +90,7 @@ def initialize_monitor(hook_config, config, config_filename, monitoring_log_leve
|
|||
)
|
||||
|
||||
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run):
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run, action_name):
|
||||
'''
|
||||
Ping the configured Healthchecks URL or UUID, modified with the monitor.State. Use the given
|
||||
configuration filename in any log entries, and log to Healthchecks with the giving log level.
|
||||
|
|
|
@ -14,7 +14,7 @@ def initialize_monitor(
|
|||
pass
|
||||
|
||||
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run):
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run, action_name):
|
||||
'''
|
||||
Ping the configured Ntfy topic. Use the given configuration filename in any log entries.
|
||||
If this is a dry run, then don't actually ping anything.
|
||||
|
|
|
@ -21,7 +21,7 @@ def initialize_monitor(
|
|||
pass
|
||||
|
||||
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run):
|
||||
def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run, action_name):
|
||||
'''
|
||||
If this is an error state, create a PagerDuty event with the configured integration key. Use
|
||||
the given configuration filename in any log entries. If this is a dry run, then don't actually
|
||||
|
|
|
@ -16,7 +16,7 @@ def test_run_configuration_runs_actions_for_each_repository():
|
|||
expected_results[1:]
|
||||
)
|
||||
config = {'repositories': [{'path': 'foo'}, {'path': 'bar'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1)}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, skip_monitoring=False)}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -30,7 +30,7 @@ def test_run_configuration_with_invalid_borg_version_errors():
|
|||
flexmock(module.dispatch).should_receive('call_hooks').never()
|
||||
flexmock(module).should_receive('run_actions').never()
|
||||
config = {'repositories': ['foo']}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'prune': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'prune': flexmock()}
|
||||
|
||||
list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -45,7 +45,7 @@ def test_run_configuration_logs_monitor_start_error():
|
|||
flexmock(module).should_receive('log_error_records').and_return(expected_results)
|
||||
flexmock(module).should_receive('run_actions').never()
|
||||
config = {'repositories': ['foo']}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -60,7 +60,7 @@ def test_run_configuration_bails_for_monitor_start_soft_failure():
|
|||
flexmock(module).should_receive('log_error_records').never()
|
||||
flexmock(module).should_receive('run_actions').never()
|
||||
config = {'repositories': ['foo']}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -76,7 +76,7 @@ def test_run_configuration_logs_actions_error():
|
|||
flexmock(module).should_receive('log_error_records').and_return(expected_results)
|
||||
flexmock(module).should_receive('run_actions').and_raise(OSError)
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False)}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False)}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -92,7 +92,7 @@ def test_run_configuration_bails_for_actions_soft_failure():
|
|||
flexmock(module).should_receive('log_error_records').never()
|
||||
flexmock(module.command).should_receive('considered_soft_failure').and_return(True)
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -109,7 +109,7 @@ def test_run_configuration_logs_monitor_log_error():
|
|||
flexmock(module).should_receive('log_error_records').and_return(expected_results)
|
||||
flexmock(module).should_receive('run_actions').and_return([])
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -127,7 +127,7 @@ def test_run_configuration_bails_for_monitor_log_soft_failure():
|
|||
flexmock(module).should_receive('run_actions').and_return([])
|
||||
flexmock(module.command).should_receive('considered_soft_failure').and_return(True)
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -144,7 +144,7 @@ def test_run_configuration_logs_monitor_finish_error():
|
|||
flexmock(module).should_receive('log_error_records').and_return(expected_results)
|
||||
flexmock(module).should_receive('run_actions').and_return([])
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -162,7 +162,7 @@ def test_run_configuration_bails_for_monitor_finish_soft_failure():
|
|||
flexmock(module).should_receive('run_actions').and_return([])
|
||||
flexmock(module.command).should_receive('considered_soft_failure').and_return(True)
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -177,7 +177,7 @@ def test_run_configuration_does_not_call_monitoring_hooks_if_monitoring_hooks_ar
|
|||
flexmock(module).should_receive('run_actions').and_return([])
|
||||
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=-2, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=-2, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == []
|
||||
|
||||
|
@ -192,7 +192,7 @@ def test_run_configuration_logs_on_error_hook_error():
|
|||
).and_return(expected_results[1:])
|
||||
flexmock(module).should_receive('run_actions').and_raise(OSError)
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -208,7 +208,7 @@ def test_run_configuration_bails_for_on_error_hook_soft_failure():
|
|||
flexmock(module).should_receive('log_error_records').and_return(expected_results)
|
||||
flexmock(module).should_receive('run_actions').and_raise(OSError)
|
||||
config = {'repositories': [{'path': 'foo'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
|
||||
|
@ -223,7 +223,7 @@ def test_run_configuration_retries_soft_error():
|
|||
flexmock(module).should_receive('run_actions').and_raise(OSError).and_return([])
|
||||
flexmock(module).should_receive('log_error_records').and_return([flexmock()]).once()
|
||||
config = {'repositories': [{'path': 'foo'}], 'retries': 1}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == []
|
||||
|
||||
|
@ -246,7 +246,7 @@ def test_run_configuration_retries_hard_error():
|
|||
OSError,
|
||||
).and_return(error_logs)
|
||||
config = {'repositories': [{'path': 'foo'}], 'retries': 1}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == error_logs
|
||||
|
||||
|
@ -264,7 +264,7 @@ def test_run_configuration_repos_ordered():
|
|||
'bar: Error running actions for repository', OSError
|
||||
).and_return(expected_results[1:]).ordered()
|
||||
config = {'repositories': [{'path': 'foo'}, {'path': 'bar'}]}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == expected_results
|
||||
|
||||
|
@ -298,7 +298,7 @@ def test_run_configuration_retries_round_robin():
|
|||
'repositories': [{'path': 'foo'}, {'path': 'bar'}],
|
||||
'retries': 1,
|
||||
}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == foo_error_logs + bar_error_logs
|
||||
|
||||
|
@ -330,7 +330,7 @@ def test_run_configuration_retries_one_passes():
|
|||
'repositories': [{'path': 'foo'}, {'path': 'bar'}],
|
||||
'retries': 1,
|
||||
}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == error_logs
|
||||
|
||||
|
@ -373,7 +373,7 @@ def test_run_configuration_retry_wait():
|
|||
'retries': 3,
|
||||
'retry_wait': 10,
|
||||
}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == error_logs
|
||||
|
||||
|
@ -412,7 +412,7 @@ def test_run_configuration_retries_timeout_multiple_repos():
|
|||
'retries': 1,
|
||||
'retry_wait': 10,
|
||||
}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False), 'create': flexmock()}
|
||||
arguments = {'global': flexmock(monitoring_verbosity=1, dry_run=False, skip_monitoring=False), 'create': flexmock()}
|
||||
results = list(module.run_configuration('test.yaml', config, arguments))
|
||||
assert results == error_logs
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ def test_ping_monitor_rewrites_ping_url_for_start_state():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -32,6 +33,7 @@ def test_ping_monitor_rewrites_ping_url_and_state_for_start_state():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -48,6 +50,7 @@ def test_ping_monitor_rewrites_ping_url_for_finish_state():
|
|||
module.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -64,6 +67,7 @@ def test_ping_monitor_rewrites_ping_url_for_fail_state():
|
|||
module.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -78,6 +82,7 @@ def test_ping_monitor_dry_run_does_not_hit_ping_url():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=True,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -95,6 +100,7 @@ def test_ping_monitor_with_connection_error_logs_warning():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -116,6 +122,7 @@ def test_ping_monitor_with_other_error_logs_warning():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -130,4 +137,5 @@ def test_ping_monitor_with_unsupported_monitoring_state_bails():
|
|||
module.monitor.State.LOG,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ from borgmatic.hooks import cronitor as module
|
|||
|
||||
|
||||
def test_ping_monitor_hits_ping_url_for_start_state():
|
||||
hook_config = {'ping_url': 'https://example.com'}
|
||||
hook_config = {'create': 'https://example.com'}
|
||||
flexmock(module.requests).should_receive('get').with_args('https://example.com/run').and_return(
|
||||
flexmock(ok=True)
|
||||
)
|
||||
|
@ -16,11 +16,12 @@ def test_ping_monitor_hits_ping_url_for_start_state():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
def test_ping_monitor_hits_ping_url_for_finish_state():
|
||||
hook_config = {'ping_url': 'https://example.com'}
|
||||
hook_config = {'create': 'https://example.com'}
|
||||
flexmock(module.requests).should_receive('get').with_args(
|
||||
'https://example.com/complete'
|
||||
).and_return(flexmock(ok=True))
|
||||
|
@ -32,11 +33,12 @@ def test_ping_monitor_hits_ping_url_for_finish_state():
|
|||
module.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
def test_ping_monitor_hits_ping_url_for_fail_state():
|
||||
hook_config = {'ping_url': 'https://example.com'}
|
||||
hook_config = {'create': 'https://example.com'}
|
||||
flexmock(module.requests).should_receive('get').with_args(
|
||||
'https://example.com/fail'
|
||||
).and_return(flexmock(ok=True))
|
||||
|
@ -48,11 +50,12 @@ def test_ping_monitor_hits_ping_url_for_fail_state():
|
|||
module.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
def test_ping_monitor_dry_run_does_not_hit_ping_url():
|
||||
hook_config = {'ping_url': 'https://example.com'}
|
||||
hook_config = {'create': 'https://example.com'}
|
||||
flexmock(module.requests).should_receive('get').never()
|
||||
|
||||
module.ping_monitor(
|
||||
|
@ -62,11 +65,12 @@ def test_ping_monitor_dry_run_does_not_hit_ping_url():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=True,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
def test_ping_monitor_with_connection_error_logs_warning():
|
||||
hook_config = {'ping_url': 'https://example.com'}
|
||||
hook_config = {'create': 'https://example.com'}
|
||||
flexmock(module.requests).should_receive('get').and_raise(
|
||||
module.requests.exceptions.ConnectionError
|
||||
)
|
||||
|
@ -79,11 +83,12 @@ def test_ping_monitor_with_connection_error_logs_warning():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
def test_ping_monitor_with_other_error_logs_warning():
|
||||
hook_config = {'ping_url': 'https://example.com'}
|
||||
hook_config = {'create': 'https://example.com'}
|
||||
response = flexmock(ok=False)
|
||||
response.should_receive('raise_for_status').and_raise(
|
||||
module.requests.exceptions.RequestException
|
||||
|
@ -100,11 +105,12 @@ def test_ping_monitor_with_other_error_logs_warning():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
def test_ping_monitor_with_unsupported_monitoring_state_bails():
|
||||
hook_config = {'ping_url': 'https://example.com'}
|
||||
hook_config = {'create': 'https://example.com'}
|
||||
flexmock(module.requests).should_receive('get').never()
|
||||
|
||||
module.ping_monitor(
|
||||
|
@ -114,4 +120,5 @@ def test_ping_monitor_with_unsupported_monitoring_state_bails():
|
|||
module.monitor.State.LOG,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
|
|
@ -148,6 +148,7 @@ def test_ping_monitor_hits_ping_url_for_start_state():
|
|||
state=module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -166,6 +167,7 @@ def test_ping_monitor_hits_ping_url_for_finish_state():
|
|||
state=module.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -184,6 +186,7 @@ def test_ping_monitor_hits_ping_url_for_fail_state():
|
|||
state=module.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -202,6 +205,7 @@ def test_ping_monitor_hits_ping_url_for_log_state():
|
|||
state=module.monitor.State.LOG,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -222,6 +226,7 @@ def test_ping_monitor_with_ping_uuid_hits_corresponding_url():
|
|||
state=module.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -240,6 +245,7 @@ def test_ping_monitor_skips_ssl_verification_when_verify_tls_false():
|
|||
state=module.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -258,6 +264,7 @@ def test_ping_monitor_executes_ssl_verification_when_verify_tls_true():
|
|||
state=module.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -273,6 +280,7 @@ def test_ping_monitor_dry_run_does_not_hit_ping_url():
|
|||
state=module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=True,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -288,6 +296,7 @@ def test_ping_monitor_does_not_hit_ping_url_when_states_not_matching():
|
|||
state=module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=True,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -305,6 +314,7 @@ def test_ping_monitor_hits_ping_url_when_states_matching():
|
|||
state=module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -323,6 +333,7 @@ def test_ping_monitor_with_connection_error_logs_warning():
|
|||
state=module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -345,4 +356,5 @@ def test_ping_monitor_with_other_error_logs_warning():
|
|||
state=module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
|
|
@ -49,6 +49,7 @@ def test_ping_monitor_minimal_config_hits_hosted_ntfy_on_fail():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -71,6 +72,7 @@ def test_ping_monitor_with_auth_hits_hosted_ntfy_on_fail():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -90,6 +92,7 @@ def test_ping_monitor_auth_with_no_username_warning():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -109,6 +112,7 @@ def test_ping_monitor_auth_with_no_password_warning():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -123,6 +127,7 @@ def test_ping_monitor_minimal_config_does_not_hit_hosted_ntfy_on_start():
|
|||
borgmatic.hooks.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -137,6 +142,7 @@ def test_ping_monitor_minimal_config_does_not_hit_hosted_ntfy_on_finish():
|
|||
borgmatic.hooks.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -155,6 +161,7 @@ def test_ping_monitor_minimal_config_hits_selfhosted_ntfy_on_fail():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -169,6 +176,7 @@ def test_ping_monitor_minimal_config_does_not_hit_hosted_ntfy_on_fail_dry_run():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=True,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -185,6 +193,7 @@ def test_ping_monitor_custom_message_hits_hosted_ntfy_on_fail():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -203,6 +212,7 @@ def test_ping_monitor_custom_state_hits_hosted_ntfy_on_start():
|
|||
borgmatic.hooks.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -222,6 +232,7 @@ def test_ping_monitor_with_connection_error_logs_warning():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -245,4 +256,5 @@ def test_ping_monitor_with_other_error_logs_warning():
|
|||
borgmatic.hooks.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
|
|
@ -13,6 +13,7 @@ def test_ping_monitor_ignores_start_state():
|
|||
module.monitor.State.START,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -26,6 +27,7 @@ def test_ping_monitor_ignores_finish_state():
|
|||
module.monitor.State.FINISH,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -39,6 +41,7 @@ def test_ping_monitor_calls_api_for_fail_state():
|
|||
module.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -52,6 +55,7 @@ def test_ping_monitor_dry_run_does_not_call_api():
|
|||
module.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=True,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -68,6 +72,7 @@ def test_ping_monitor_with_connection_error_logs_warning():
|
|||
module.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
||||
|
||||
|
@ -86,4 +91,5 @@ def test_ping_monitor_with_other_error_logs_warning():
|
|||
module.monitor.State.FAIL,
|
||||
monitoring_log_level=1,
|
||||
dry_run=False,
|
||||
action_name='create',
|
||||
)
|
||||
|
|
nit(pythonic):
next(iter(arguments))
Also, if we are only using this variable when
using_primary_action
, it might make sense to rename it toprimary_aciton_name
and/or move it where it's needed too.Thanks, that's definitely more effecient.
If I'm reading this correctly, this will just grab the first action. But there could very well be multiple actions at once, and I'd expect Cronitor to be pinged for each one (if configured for each one).
@witten I unexpectedly missed that multiple actions. Will fix it.
Why
getattr()
? Doesn't the attribute always exist now that you've added it to the global arguments? So would justglobal_arguments.skip_monitoring
work? I don't even think you need theFalse
here becauseaction='store_true'
above defaults to False if not specified.