Conditions
Conditions are at the heart of whenever, by triggering the execution of tasks. As mentioned before, several types of condition are supported. Part of the configuration is common to all conditions, that is:
Entry |
Default |
Description |
---|---|---|
|
N/A |
the unique name of the condition (mandatory) |
|
N/A |
string describing the type of condition (mandatory, one of the possible values) |
|
false |
if false, the condition is not checked anymore after first successful verification |
|
0 |
how many times the tasks will be retried, when at least one of them fails, in non recurring conditions |
|
true |
if true the associated tasks are executed one after the other, in the order in which they are listed |
|
false |
if true, task execution stops after the first successfully executed task (when
|
|
false |
if true, task execution stops after the first failed task (when |
|
false |
if true, the condition will not be checked nor the associated tasks executed |
|
|
a list of task names that will be executed upon condition verification |
When execute_sequence
is set to false, the associated tasks are started concurrently in the
same instant, and task outcomes are ignored. Otherwise a minimal control flow is implemented,
allowing the sequence to be interrupted after the first success or failure in task execution. Note
that it is possible to set both break_on_success
and break_on_failure
to true.[1]
The type
entry can be one of: "interval"
, "time"
, "idle"
, "command"
,
"lua"
, "event"
, "dbus"
, and "wmi"
. Any other value is considered a
configuration error.
Note
The "dbus"
and "wmi"
values will be considered an error if the respective features are
not available.
For conditions that should be periodically checked and whose associated task list has to be run
whenever they occur (and not just after the first occurrence), the recurring
entry can be set
to true. Conditions with no associated tasks (eg. when the user comments out all the associated
tasks in the configuration file) are not checked.
The max_tasks_retries
field indicates how many times the execution of a failed task, or a set
of tasks of which at least one has failed, will be retried in non recurring conditions when the
condition check is successful: a value of N indicates that the check will be performed at most
N times after the first failure in tasks before giving up checking. If all the tasks succeed at
the first time or within the provided number of retries, the non recurring condition will cease
its checks anyway. A provided value of -1
instructs whenever that the checks must continue
indefinitely until all the associated tasks succeed, a value of 0
indicates that there should
be no retries after the first unsuccessful run. Values below -1
are not admitted. This
parameter is ignored in recurring conditions. Tasks whose outcome is not checked do not count
as unsuccessful. If break_on_success
is true and the first task in a sequence has a positive
oucome, the entire sequence is considered successful: in other words, only tasks that have been
executed count for outcome verification.
The suspended
entry can assume a true value for conditions for which the user does not want
to remove the configuration but should be (at least temporarily) prevented. However, a condition
that is suspended by configuration can be awakened using an interactive command (usually by a
wrapper): input commands passed via the stdin based interface
can be used to suspend and resume condition checks when the scheduler is running.
There is another optional entry, namely tags
, that is accepted in item configuration: this
entry is ignored by whenever itself, however it is checked for correctness at startup and the
configuration is refused if not set to an array (of strings) or a table.
Another entry is common to several condition types, that is check_after: it can be set to the number of seconds that whenever has to wait after startup (and after the last check for _recurring_ conditions) for a subsequent check: this is useful for conditions that can run on a more relaxed schedule, or whose check process has a significant cost in terms of resources, or whose associated task sequence might take a long time to finish. Simpler conditions and conditions based on time do not accept this entry.
Some condition types can set the recur_after_failed_check
flag: it allows for avoidance of
multiple subsequent task runs in case of a persistent situation that causes recurring condition
checks to be successful: the associated tasks are run as soon as the check is successful for the
first time, then task execution is prevented as long as this status persists. After at least one
unsuccessful condition check (in which, of course, the tasks are not executed), at the following
successful one the task run is performed again.
While a condition check or the execution of an associated task sequence is underway, the condition is marked as busy, and while a condition is in this state no further checks are performed. The condition is released from its busy state only after all checks and tasks have been performed. This is important when long-running checks and tasks are requested, as this flag ensures that checks and tasks for a single long-running and recurring activity cannot overlap.
Note that all listed tasks must be defined, otherwise an error is raised and whenever will not start.
The following paragraphs describe in detail each condition type. For the sake of brevity, only specific configuration entries will be described for each type.
All condition definition sections must start with the TOML [[condition]]
header.
Interval
Interval based conditions are verified after a certain amount of time has passed, either since
startup or after the last successful check. This type of condition is useful for tasks that should
be executed periodically, thus most of the times recurring
will be set to true for this type
of condition. The following is an example of interval based condition:
[[condition]]
name = "IntervalConditionName"
type = "interval"
interval_seconds = 3600
# optional parameters (if omitted, defaults are used)
recurring = false
max_tasks_retries = 0
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = true
tasks = [
"Task1",
"Task2",
]
describing a condition that is verified one hour after whenever has started, and not anymore
after the first occurrence – because recurring
is false here and no retries are allowed.
Were it true, the condition would be verified every hour.
The specific parameters for this type of condition are:
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
|
N/A |
the number of seconds to wait for the condition to be verified (mandatory) |
The check for this type of condition is never randomized.
Time
Time based conditions occur just after one of the provided time specifications has been reached. Time specifications are given as a list of tables, each of which can contain one or more of the following entries:
hour
: the hour, as an integer between 0 and 23minute
: the minute, as an integer between 0 and 59second
: the second, as an integer between 0 and 59year
: an integer expressing the (full) yearmonth
: an integer expressing the month, between 1 (January) and 12 (December)day
: an integer expressing the day of the month, between 1 and 31weekday
: the name of the weekday in English, either whole or abbreviated to three letters.
Not all the entries must be specified: for instance, specifying the day of week and a full date (as year, month, date) may cause the event to never occur if that particular date does not occur on that specific week day. Normally a day of the month will be specified, and then a time of the day, or a weekday and a time of the day. However full freedom is given in specifying or omitting part of the date:
missing parts in the date will be considered verified at every change of each of them (years, months, days, and weekdays)
a missing hour specification will be considered verified at every hour
a missing minute or second specification will be considered verified respectively at the first minute of the hour and first second of the minute.
Of course, all the time specifications in the provided list will be checked at each tick: this allows complex configurations for actions that must be performed at specific times.
A sample configuration section follows:
[[condition]]
name = "TimeConditionName"
type = "time" # mandatory value
# optional parameters (if omitted, defaults are used)
time_specifications = [
{ hour = 17, minute = 30 },
{ hour = 12, minute = 0, weekday = "wed" },
]
recurring = true
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = true
tasks = [
"Task1",
"Task2",
]
for a condition that is verified everyday at 5:30PM and every Wednesday at noon. The specific parameters are:
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
|
|
a list of partial time specifications, as inline tables consisting of the above described entries (mandatory) |
The check for this type of condition is never randomized.
Idle session
Conditions of the idle type are verified after the session has been idle (that is, without user interaction), for the specified number of seconds.[2] This does normally not interfere with other idle time based actions provided by the environment such as screensavers, and automatic session lock. The following is a sample configuration for this type of condition:
[[condition]]
name = "IdleConditionName"
type = "idle"
idle_seconds = 3600
# optional parameters (if omitted, defaults are used)
recurring = true
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = true
tasks = [
"Task1",
"Task2",
]
for a condition that will be verified each time that an hour has passed since the user has been
away from the mouse and the keyboard. For tasks that usually occur only once per session when the
workstation is idle (such as backups, for instance), recurring
can be set to false. The
table below describes the specific configuration entries:
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
|
N/A |
the number of idle seconds to be waited for in order to consider the condition verified (mandatory) |
The check for this type of condition is never randomized.
Command
This type of condition gives the possibility to execute an OS command and decide whether or not the condition is verified testing the command exit code and/or what the command writes on its standard output or standard error channel. The available checks are of the same type as the ones available for command based tasks. In fact it is possible to:
identify a provided exit code as a failure or as a success
specify that the presence of a substring or matching a regular expression in what the command provides as output (on both stdout and stderr) corresponds to either a failure or a success.
When a success rule is specified (that is, one of the parameters with the success_
prefix),
the verification of that rule is considered a successful outcome, and outcomes that do not satisfy
any given success rule are identified as failures. On the other hand, if a failure rule is set,
then outcomes that match that rule are considered failures: any other outcome is successful.
Tip
Setting both success and failure rules is actually possible, however it is not really useful because of the priority that is used when checking for success or failure in the execution of a command. Success is checked first, and in the following order:
exit code correspondance
standard input search or match
standard error search or match
and then, if none of these rules (if provided) is matched, failure is checked in the same order. Therefore, if one or more success rules are given, not matching them is considered a failure anyway and the failure rules are simply skipped.
Most of the times it is useful to just provide one or two criteria, either on the success or on the failure side only.
As for command based tasks, it is not mandatory to follow the usual conventions – this means, for instance, that a zero exit code can be identified as a failure and a non-zero exit code as a success.
If a command is known to have the possibility to hang, a timeout can be configured by specifying the maximum number of seconds to wait for the process to exit: after this amount of time the process is terminated and fails.
An example of command based condition follows:
[[condition]]
name = "CommandConditionName"
type = "command" # mandatory value
startup_path = "/some/startup/directory" # must exist
command = "executable_name"
command_arguments = [
"arg1",
"arg2",
]
# optional parameters (if omitted, defaults are used)
recurring = false
max_tasks_retries = 3
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = false
tasks = [
"Task1",
"Task2",
]
check_after = 10
recur_after_failed_check = true
match_exact = false
match_regular_expression = false
success_stdout = "expected"
success_stderr = "expected_error"
success_status = 0
failure_stdout = "unexpected"
failure_stderr = "unexpected_error"
failure_status = 2
timeout_seconds = 60
case_sensitive = false
include_environment = true
set_environment_variables = true
environment_variables = { VARNAME1 = "value1", VARNAME2 = "value2" }
Note that the recurring
flag is false
, and max_tasks_retries
is set to 3: this
means that the check will be performed three more times after the first unsuccessful run of
the associated tasks.
The following table illustrates the parameters specific to command based conditions:
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
|
(empty) |
number of seconds that have to pass before the condition is checked the first time or
further times if |
|
false |
if set to true and |
|
N/A |
the directory in which the command is started (mandatory) |
|
N/A |
path to the executable (mandatory; if the path is omitted, the executable should be found in the search PATH) |
|
N/A |
arguments to pass to the executable: can be an empty list, |
|
false |
if true, the entire output is matched instead of searching for a substring |
|
false |
if true, the match strings are considered regular expressions instead of substrings |
|
false |
if true, substring search or match and regular expressions match is performed case-sensitively |
|
(empty) |
if set, the number of seconds to wait before the command is terminated (with unsuccessful outcome) |
|
(empty) |
if set, when the execution ends with the provided exit code the condition is considered verified |
|
(empty) |
if set, when the execution ends with the provided exit code the condition is considered failed |
|
(empty) |
the substring or RE to be found or matched on stdout to consider the task successful |
|
(empty) |
the substring or RE to be found or matched on stderr to consider the task successful |
|
(empty) |
the substring or RE to be found or matched on stdout to consider the task failed |
|
(empty) |
the substring or RE to be found or matched on stderr to consider the task failed |
|
true |
if true, the command is executed in the same environment in which whenever was started |
|
true |
if true, whenever sets environment variables reporting the names of the task and the condition |
|
|
extra variables that might have to be set in the environment in which the provided command runs |
If set_environment_variables
is true, whenever sets the following environment variable:
WHENEVER_CONDITION
to the unique name of the condition that is currently being tested
for scripts or other executables used in checks that might be aware of whenever.
For this type of condition the actual test can be performed at a random time within the tick interval.
Lua script
A Lua script can be used to determine the verification of a condition: after the execution of the script, one or more variables can be checked against expected values and thus decide whether or not the associated tasks have to be run. Given the power of Lua and its standard library, this type of condition can constitute a lightweight alternative to complex scripts to call to implement a command based condition. The definition of a Lua condition is actually much simpler:
[[condition]]
name = "LuaConditionName"
type = "lua" # mandatory value
script = '''
log.info("hello from Lua");
result = 10;
'''
# optional parameters (if omitted, defaults are used)
recurring = false
max_tasks_retries = -1
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = false
tasks = [
"Task1",
"Task2",
]
check_after = 10
recur_after_failed_check = false
expect_all = false
expected_results = { result = 10 }
Note that the recurring
flag is false
, and max_tasks_retries
is set to -1: this
means that the check will be performed until all the associated tasks are executed
successfully.
The specific parameters are described in the following table:
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
|
(empty) |
number of seconds that have to pass before the condition is checked the first time
or further times if |
|
false |
if set to true and |
|
N/A |
the Lua code that has to be executed by the internal interpreter (mandatory) |
|
false |
if true, all the expected results have to be matched to consider the task successful, otherwise at least one |
|
|
a dictionary of variable names and their expected values to be checked after execution |
The same rules and possibilities seen for Lua based tasks also apply to conditions: the embedded Lua interpreter is enriched with library functions that allow to write to the whenever log, at all logging levels (error, warn, info, debug, trace). The library functions are the following:
log.error
log.warn
log.info
log.debug
log.trace
and take a single string as their argument. Also, from the embedded Lua interpreter there is a value that can be accessed:
whenever_condition
is the name of the condition being checked.
External scripts can be executed via dofile("/path/to/script.lua")
or by using the require
function. While a successful execution is always determined by matching the provided criteria, an
error in the script is always considered a failure.
The recur_after_failed_check
flag allows for avoidance of multiple subsequent task runs in case
of a persistent situation that cause the condition checks to be successful if the condition is
marked as recurring: the associated tasks are run as soon as the check is successful for the
first time, then the tasks are not executed anymore as long as this status persists. After at least
one unsuccessful condition check (in which, of course, the tasks are not executed), at the
following successful one the task run is performed again.
For this type of condition the actual test can be performed at a random time within the tick interval.
DBus method (optional)
The return message of a DBus method invocation is used to determine the execution of the tasks associated to this type of condition. Due to the nature of DBus, the configuration of a DBus based condition is quite complex, both in terms of definition of the method to be invoked, especially for what concerns the parameters to be passed to the method, and in terms of specifying how to test the result.[3]
Note
This type of item is only available when the dbus
feature is enabled.
So, as a rule of thumb:[4]
arguments to be passed to the DBus method are specified in a list
criteria to determine expected return values (aka messages, which can be complex structures) are expressed a list of tables of three elements each (inline tables can be used for readability), that is:
"index"
: a list of elements, which can be either integers or strings representing each a positional 0-based index or a string (or object path) key in a dictionary; this allows to index deeply nested structures in which part of the nested elements are dictionaries"operator"
: one of the following strings"eq"
for equality"neq"
for inequality"gt"
meaning greater than"ge"
meaning greater or equal to"lt"
meaning less than"le"
meaning less or equal to"match"
to indicate that the second operand has to be intended as a regular expression to be matched"contains"
to indicate that the second operand is contained in the first operand (see below)"ncontains"
to indicate that the second operand is not contained in the first operand
"value"
: the second operand for the specified operator.
Note
The first element of the "index"
field is always a zero-based integer:
this ia because a message is supposed to consist of an array of numbered fields:
if a single value is returned, which can also be as complex as a nested dictionary,
it is considered to be the first field (having 0 as index) of the return message,
thus 0 must be specified as the first value in the index.
Please notice that not all types of operand are supported for all operators: comparisons
(greater and greater or equal, less and less or equal) are only supported
for numbers, and matching is only supported for strings. The "contains"
/"ncontains"
operators support non-structured types for the second operand (booleans, numbers, and strings)
and either strings (and object paths) or arrays and dictionaries for the first one: if the first
operand is an array the second operand is searched in the list and the check is true when it is
found, in case it is a dictionary then the second operand (which should be a string) is searched
among the keys of the dictionary, and if the first operand is either a string or an object path,
the check is true when the second one is a substring. Also, comparisons always fail for
incompatible operands: integers can only be compared with integers, floating point numbers with
floating point numbers and strings with strings – no automatic type conversion is performed. This
also yields for attempts to find a value in an array: an integer will never be found in an array of
floating point numbers, and so on. To be consistent with the rule of unsuccessfulness on incompatible
operands, the "ncontains"
operator too is unsuccessful when the operands cannot be compared,
even though, from another point of view, the opposite could have been seen as appropriate.
A further difficulty is due to the fact that, while DBus is strictly typed and supports all the basic types supported by C and C++, TOML does not. TOML has instead more generic types, which are listed below along with the DBus type to which whenever converts them in method invocation:
Boolean:
BOOLEAN
Integer:
I64
Float:
F64
String:
STRING
List:
ARRAY
Map:
DICTIONARY
This means that there are a lot of value types that are not directly derived from the native TOML
types. whenever comes to help by allowing to express strictly typed values by using specially
crafted strings. These string must begin with a backslash, \
(in the TOML representation it
has to be doubled in order to escape it, or a literal string must be used), followed by the
signature character (ASCII Type Code in the basic type table[5]) identifying the
type. For example, the string '\y42'
indicates a BYTE
parameter holding 42 as the value,
while '\o/com/example/MusicPlayer1'
indicates an OBJECT_PATH
[6] containing the value
/com/example/MusicPlayer1. A specially crafted string will be translated into a specific value of
a specific type only when a supported ASCII Type Code is used, in all other cases the string is
interpreted literally: for instance, '\w100'
is translated into a STRING
holding the value
w100.
For return values, while the structure of complex entities received from DBus is kept, all values
are automatically converted to more generic types: a returned BYTE
is converted to a TOML
Integer, and a returned OBJECT_PATH
is consdered a TOML String which, as a side effect,
supports the "match"
operator.
An example of DBus method based condition follows:
[[condition]]
name = "DbusMethodConditionName"
type = "dbus" # mandatory value
bus = ":session" # either ":session" or ":system"
service = "org.freedesktop.DBus"
object_path = "/org/freedesktop/DBus"
interface = "org.freedesktop.DBus"
method = "NameHasOwner"
# optional parameters (if omitted, defaults are used)
recurring = true
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = true
tasks = [ "Task1", "Task2" ]
check_after = 60
recur_after_failed_check = false
parameter_call = [
"SomeObject",
[42, "a structured parameter"],
["the following is an u64", "\\t42"],
]
parameter_check_all = false
parameter_check = [
{ index = 0, operator = "eq", value = false },
{ index = [1, 5], operator = "neq", operator = "forbidden" },
{ index = [2, "mapidx", 5], operator = "match", value = "^[A-Z][a-zA-Z0-9_]*$" },
]
As shown below, parameter_check
is the list of criteria against which the return message parameters
(the invocation results are often referred to with this terminology in DBus jargon): for what has
been explained above, the checks are performed like this:
the first element (thus with 0 as index) of the returned array is expected to be a boolean and to be false
the second element is considered to be an array, whose sixth element (with index 5) must not be the string “forbidden”
the third element is highly nested, containing a map whose element with key “mapidx” is an array, containing a string at its sixth position, which should be alphanumeric and begin with a capital letter, and may contain underscores (that is, matches the regular expression
^[A-Z][a-zA-Z0-9_]*$
).
Note that the first check shows a 0
index not embedded in a list: if a returned parameter is
not an array or a dictionary and its value is required directly, the square brackets around this
single index can be omitted and whenever does not complain. Since this is probably the most
frequent use case, this is a way to make configuration more readable and concise in such cases.
Since parameter_check_all
is false, satisfaction of one of the provided criteria is
sufficient to determine the success of the condition.
The specific parameters are described in the following table:
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
|
(empty) |
number of seconds that have to pass before the condition is checked the first time or further
times if |
|
false |
if set to true and |
|
N/A |
the bus on which the method is invoked: must be either |
|
N/A |
the name of the service that exposes the required object and the interface to invoke or query (mandatory) |
|
N/A |
the object exposing the interface to invoke or query (mandatory) |
|
N/A |
the interface to invoke or query (mandatory) |
|
N/A |
the name of the method to be invoked (mandatory) |
|
(empty) |
a structure, expressed as a list, containing exactly the parameters that shall be passed to the method |
|
false |
if true, all the provided criteria will have to be satisfied for the condition to be successful, otherwise one is enough |
|
(empty) |
a list of maps having the structure explained above |
The value corresponding to the service
entry is often referred to as bus name in various
documents: here service is preferred to avoid confusing it with the actual bus, which is
either the session bus or the system bus.
Methods resulting in an error will always be considered as failed: therefore it is possible to avoid to provide return value criteria, and just consider a successful invocation as a success and an error as a failure. Also, any errors that may arise during checks will cause the check itself to yield false.
Note that DBus based conditions are supported on Windows, however DBus should be running for such conditions to be useful – which is very unlikely to say the least.
The recur_after_failed_check
flag allows for avoidance of multiple subsequent task runs in case
of a persistent situation that cause the condition checks to be successful if the condition is
marked as recurring: the associated tasks are run as soon as the check is successful for the
first time, then the tasks are not executed anymore as long as this status persists. After at least
one unsuccessful condition check (in which, of course, the tasks are not executed), at the following
successful one the task run is performed again.
For this type of conditions the actual test can be performed at a random time within the tick interval.
WMI Query (optional, Windows only)
On Windows, whenever allows to directly query the WMI subsystem, which is a powerful way to retrieve information. WMI is accessed via a query language called WQL, which is syntactically and semantically close to SQL. Queries normally return lists of compound values where every component has a name. For analogy with database operations and queries, this document will refer the returned compound values as rows or records, and their components as fields.
Note
This type of item is only available when the wmi
feature is enabled.
WMI inquiries are somewhat simpler than their DBus counterparts, mostly because the query language is more structured and allows for more complex filtering at the query level. Because of that, and since a query can be crafted in order to directly return the values of interest without having to deeply inspect returned objects, whenever will only inspect fields containing simple values (numbers, booleans, and strings) in a query result.
The main part of a WMI Query based condition is obviously the query itself, which is provided
as a freeform string using the mandatory query
configuration entry. whenever does not do
any parsing or check on the provided query, thus an incorrect query will only cause the condition
test to always fail and log an error message, at least in the debug log level.
Since a WMI query returns a set of records, it is possible to filter the returned rows by providing criteria: this can be done using the _resultcheck entry, provided as a list of dictionaries, each representing a check, having the following entries:
index
is the index of the row in the result set that will be checked (this sub-entry is optional, leaving it out means any row)field
indicates which record field is checked, and must be a stringoperator
is the check operator, a string of the ones shown belowvalue
is the value that the field is checked against, and its type must be compatible with the field value.
Operators resemble the ones used for DBus return message value comparisons, with the exception that, since no complex values such as arrays or dictionaries are expected to be tested, operators that check for inclusion are not available. The supported operators are, therefore:
"eq"
for equality"neq"
for inequality"gt"
meaning greater than"ge"
meaning greater or equal to"lt"
meaning less than"le"
meaning less or equal to"match"
to indicate that the second operand has to be intended as a regular expression to be matched.
and work for all supported values in the usual way, taking out "match"
that can obviously only
be applied to strings. Note that integers and floating point numbers can be compared to each other,
with all the known issues related to this kind of comparison.
An example of WMI Query based condition configuration is the following:
[[condition]]
name = "WMIQueryConditionName"
type = "wmi" # mandatory value
query = '''
SELECT * FROM Win32_LogicalDisk WHERE FileSystem = 'NTFS'
'''
# optional parameters (if omitted, defaults are used)
recurring = true
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = true
tasks = [ "Task1", "Task2" ]
check_after = 60
recur_after_failed_check = false
result_check = [
{ field = "FreeSpace", operator = "lt", value = 5_000_000_000 },
]
result_check_all = false
The above condition definition queries the WMI subsystem to report basic information about the
logical drives handled by the system, and is successful if any of them has roughly less than 5GB
left. The test is performed every minute. Of course, the result_check
part coul also be
incorporated in the query itself, using an AND clause.
The specific parameters are described in the following table:
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
|
(empty) |
number of seconds that have to pass before the condition is checked the first time or
further times if |
|
false |
if set to true and |
|
N/A |
the WQL query used to inquire the system |
|
false |
if true, all the provided criteria will have to be satisfied for the condition to be successful, otherwise one is enough |
|
(empty) |
a list of maps having the structure explained above |
Note that it is not mandatory to provide criteria to filter the query result: their omission causes
the condition to be successful if the query returns at least one row. Also, omitting the index on
a check causes that single check to be performed on every returned row: this means that, for
instance, if all the provided checks omit the row index, even though whenever is instructed to
consider the test successful when all the provided criteria are satisfied (setting the
result_check_all
entry to true), the test will be successful if there is at least one row
satisfying each check – and not just one row satisfying all the checks. This is because the tests
that whenever applies to the result sets are intended to be simple in order to keep the
configuration file as readable as possible (and the configuration of DBus inquiries is a failure
in this sense). However, more complex and fine-grained criteria can be kept at the query level.
As said above, any error will cause the condition to be evaluated as unsuccessful.
Event
Conditions that are fired by events are referred to here both as event conditions and as bucket conditions. The reason for the second name is that every time that whenever catches an event that has been required to be monitored, it tosses the associated condition in a sort of execution bucket, that is checked by the scheduler at every tick: the scheduler withdraws every condition found in the bucket and runs the associated tasks. In facts, these conditions only exist as a connection between the events, that occur asynchronously, and the scheduler. Their configuration is therefore very simple, as seen in this example:
[[condition]]
name = "BucketConditionName"
type = "bucket" # "bucket" or "event" are the allowed values
# optional parameters (if omitted, defaults are used)
recurring = false
max_tasks_retries = 0
execute_sequence = true
break_on_failure = false
break_on_success = false
suspended = false
tasks = [
"Task1",
"Task2",
]
that is, these conditions have no specific fields, if not for the mandatory type
that should
be either "bucket"
or "event"
(with no operational difference, at least for the moment
being):
Entry |
Default |
Description |
---|---|---|
|
N/A |
has to be set to |
These conditions are associated to events for verification, no other criteria can be specified.
For this type of conditions the actual test can be performed at a random time within the tick interval.