Skip to content

Commit 42ee590

Browse files
committed
feat(docker-info, podman-info): add --ignore regex parameter for stderr warnings
Both plugins parse the daemon stderr for "warning:" and "error:" lines and escalate them to WARN/CRIT. On hosts where the kernel does not expose swap accounting (Docker) or where cgroup v2 has not been enabled yet (Podman), these stderr lines cannot be silenced in the daemon config and force the admin to live with perpetual WARN state. --ignore accepts a Python regex, is case-sensitive by default (use (?i) for case-insensitive matching), is repeatable, and matches against individual stderr lines before the warning/error escalation. Follows the filter-parameter convention tracked in #1068. Both plugins were updated in the same commit because they share the same stderr-parsing code path: the bug is the same in both, and the fix would otherwise be an inconsistency across the docker-*/podman-* plugin pair. The unit-test suites are now structurally mirrored (same test ids, same scenarios, same assertions), differing only in the stdout fixture and the daemon-specific warning/error strings (bridge-nf-call for docker, cgroup v1 for podman). Fixture names follow the CONTRIBUTING convention (describe the shape of the data, not the state). Closes #834
1 parent 89c2e4d commit 42ee590

File tree

13 files changed

+314
-41
lines changed

13 files changed

+314
-41
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Monitoring Plugins:
3535
* by-winrm: executes commands on remote Windows hosts by WinRM, supporting JEA (including the JEA endpoint via `--winrm-configuration-name`)
3636
* infomaniak-swiss-backup-devices: add `--ignore-customer`, `--ignore-name`, `--ignore-tag`, `--ignore-user` parameters to skip devices by regex
3737
* infomaniak-swiss-backup-products: add `--ignore-customer`, `--ignore-tag` parameters to skip products by regex
38+
* docker-info, podman-info: add `--ignore` parameter to filter stderr warnings and errors by regex, e.g. to suppress the `WARNING: No swap limit support` message from `docker info` on kernels without swap accounting, or the `WARNING: bridge-nf-call-iptables is disabled` message on Debian hosts that do not load the `br_netfilter` module. Accepts a Python regex, is case-sensitive by default (use `(?i)` for case-insensitive matching) and can be specified multiple times. The same treatment was applied to both plugins because they share the same stderr-parsing code path ([#834](https://github.com/Linuxfabrik/monitoring-plugins/issues/834))
3839
* haproxy-status: add `--ignore` parameter to filter out proxies, frontends, backends or servers by regex on the combined `<proxy>/<svname>` identifier, e.g. to skip an on-demand certbot backend that is only UP during cert renewal ([#835](https://github.com/Linuxfabrik/monitoring-plugins/issues/835))
3940
* ipmi-sel: add `--ignore` parameter to filter out SEL entries by regex, e.g. auto-generated "Log area reset/cleared" entries after `ipmitool sel clear` ([#982](https://github.com/Linuxfabrik/monitoring-plugins/issues/982))
4041
* json-values: add `--token` and `--header` parameters for HTTP bearer-token and custom header authentication when fetching JSON from protected endpoints, add `--warning-key` / `--warning` and `--critical-key` / `--critical` to alert on a numeric value at a specific JSON key (with Nagios range syntax), and support dot-notation for nested keys in all `--*-key` parameters (e.g. `--state-key=meta.state`) ([#1005](https://github.com/Linuxfabrik/monitoring-plugins/issues/1005))

check-plugins/docker-info/README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,30 @@ Displays system-wide Docker information including container counts (running, pau
2626
## Help
2727

2828
```text
29-
usage: docker-info [-h] [-V] [--always-ok] [--test TEST]
29+
usage: docker-info [-h] [-V] [--always-ok] [--ignore IGNORE] [--test TEST]
3030
3131
Displays system-wide Docker information including container counts (running,
3232
paused, stopped), image count, storage and logging driver, Docker version,
33-
available CPUs, and total memory. Also monitors the Docker daemon for warnings
34-
or errors. For Podman, use the podman-info check instead. Requires root or
35-
sudo.
33+
available CPUs, and total memory. Also monitors the Docker daemon stderr for
34+
warnings and errors. Individual stderr lines can be filtered out with --ignore
35+
(e.g. the "WARNING: No swap limit support" message on hosts where the kernel
36+
does not expose swap accounting). For Podman, use the podman-info check
37+
instead. Requires root or sudo.
3638
3739
options:
38-
-h, --help show this help message and exit
39-
-V, --version show program's version number and exit
40-
--always-ok Always returns OK.
41-
--test TEST For unit tests. Needs "path-to-stdout-file,path-to-stderr-
42-
file,expected-retc".
40+
-h, --help show this help message and exit
41+
-V, --version show program's version number and exit
42+
--always-ok Always returns OK.
43+
--ignore IGNORE Ignore stderr lines matching this Python regular
44+
expression. Case-sensitive by default; use `(?i)` for case-
45+
insensitive matching. Can be specified multiple times.
46+
Example: `--ignore="No swap limit support"` to suppress the
47+
Docker warning on kernels without swap accounting. Example:
48+
`--ignore="(?i)bridge-nf-call"` (case-insensitive) to
49+
suppress both `bridge-nf-call-iptables` and `bridge-nf-
50+
call-ip6tables` warnings on Debian hosts. Default: None
51+
--test TEST For unit tests. Needs "path-to-stdout-file,path-to-stderr-
52+
file,expected-retc".
4353
```
4454

4555

check-plugins/docker-info/docker-info

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"""See the check's README for more details."""
1212

1313
import argparse
14+
import re
1415
import sys
1516

1617
import lib.args
@@ -21,12 +22,14 @@ import lib.shell
2122
from lib.globals import STATE_CRIT, STATE_OK, STATE_UNKNOWN, STATE_WARN
2223

2324
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
24-
__version__ = '2026040802'
25-
26-
DESCRIPTION = """Displays system-wide Docker information including container counts (running, paused,
27-
stopped), image count, storage and logging driver, Docker version, available CPUs,
28-
and total memory. Also monitors the Docker daemon for warnings or errors. For Podman,
29-
use the podman-info check instead.
25+
__version__ = '2026041404'
26+
27+
DESCRIPTION = """Displays system-wide Docker information including container counts (running,
28+
paused, stopped), image count, storage and logging driver, Docker version, available
29+
CPUs, and total memory. Also monitors the Docker daemon stderr for warnings and errors.
30+
Individual stderr lines can be filtered out with --ignore (e.g. the "WARNING: No swap
31+
limit support" message on hosts where the kernel does not expose swap accounting). For
32+
Podman, use the podman-info check instead.
3033
Requires root or sudo."""
3134

3235

@@ -49,6 +52,22 @@ def parse_args():
4952
default=False,
5053
)
5154

55+
parser.add_argument(
56+
'--ignore',
57+
help='Ignore stderr lines matching this Python regular expression. '
58+
'Case-sensitive by default; use `(?i)` for case-insensitive matching. '
59+
'Can be specified multiple times. '
60+
'Example: `--ignore="No swap limit support"` to suppress the Docker '
61+
'warning on kernels without swap accounting. '
62+
'Example: `--ignore="(?i)bridge-nf-call"` (case-insensitive) to '
63+
'suppress both `bridge-nf-call-iptables` and `bridge-nf-call-ip6tables` '
64+
'warnings on Debian hosts. '
65+
'Default: %(default)s',
66+
dest='IGNORE',
67+
action='append',
68+
default=None,
69+
)
70+
5271
parser.add_argument(
5372
'--test',
5473
help=lib.args.help('--test'),
@@ -69,6 +88,17 @@ def main():
6988
except SystemExit:
7089
sys.exit(STATE_UNKNOWN)
7190

91+
if args.IGNORE is None:
92+
args.IGNORE = []
93+
94+
# compile ignore patterns (case-sensitive by default, matching the
95+
# lib.args convention for --match / --ignore-regex; the user can
96+
# opt into case-insensitive matching with the inline `(?i)` flag).
97+
try:
98+
ignore_patterns = [re.compile(p) for p in args.IGNORE]
99+
except re.error as e:
100+
lib.base.cu(f'Invalid regular expression: {e}')
101+
72102
# fetch data
73103
if args.TEST is None:
74104
stdout, stderr, retc = lib.base.coe(
@@ -120,8 +150,13 @@ def main():
120150
if ' server version: ' in lcrow:
121151
ver = lcrow.replace('server version: ', '').strip()
122152

123-
# check stderr for warnings and errors
153+
# check stderr for warnings and errors, skipping lines matched by
154+
# --ignore (#834: let admins suppress boilerplate docker warnings
155+
# like "WARNING: No swap limit support" that cannot be silenced in
156+
# the daemon config).
124157
for row in stderr.strip().split('\n'):
158+
if any(pattern.search(row) for pattern in ignore_patterns):
159+
continue
125160
lcrow = row.lower()
126161
if 'warning: ' in lcrow:
127162
warn += f'{row}, '

check-plugins/docker-info/icingaweb2-module-director/docker-info.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"arguments": {
55
"--always-ok": {
66
"set_if": "$docker_info_always_ok$"
7+
},
8+
"--ignore": {
9+
"value": "$docker_info_ignore$",
10+
"repeat_key": true
711
}
812
},
913
"command": "/usr/bin/sudo /usr/lib64/nagios/plugins/docker-info",
@@ -13,6 +17,11 @@
1317
"datafield_id": 1,
1418
"is_required": "n",
1519
"var_filter": null
20+
},
21+
{
22+
"datafield_id": 2,
23+
"is_required": "n",
24+
"var_filter": null
1625
}
1726
],
1827
"imports": [],
@@ -67,7 +76,8 @@
6776
"use_var_overrides": null,
6877
"vars": {
6978
"criticality": "C",
70-
"docker_info_always_ok": false
79+
"docker_info_always_ok": false,
80+
"docker_info_ignore": []
7181
},
7282
"volatile": null,
7383
"zone": null,
@@ -83,6 +93,17 @@
8393
"format": null,
8494
"settings": {},
8595
"uuid": "cc716b85-a077-4f0c-803e-c4eaa2826bd4"
96+
},
97+
"2": {
98+
"varname": "docker_info_ignore",
99+
"caption": "Docker Info: Ignore",
100+
"description": "Ignore stderr lines matching this Python regular expression. Case-sensitive by default; use `(?i)` for case-insensitive matching. Can be specified multiple times.",
101+
"datatype": "Icinga\\Module\\Director\\DataType\\DataTypeArray",
102+
"format": null,
103+
"settings": {
104+
"visibility": "visible"
105+
},
106+
"uuid": "fcf4f50c-864d-43d5-b8a2-93bbc400c4ed"
86107
}
87108
}
88109
}

check-plugins/docker-info/unit-test/run

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,88 @@ sys.path.insert(0, '..')
1515
import unittest
1616

1717
import lib.lftest
18-
from lib.globals import STATE_CRIT
18+
from lib.globals import STATE_CRIT, STATE_OK, STATE_UNKNOWN, STATE_WARN
1919

20+
# docker-info and podman-info share the same stderr-parsing code path
21+
# and the same --ignore handling (#834, #1068). The two test suites are
22+
# kept structurally identical: same test ids, same scenarios, same
23+
# assertions. Only the stdout fixture and the `check` attribute differ.
24+
# The stderr/two-warnings-two-errors fixture exists under both plugin
25+
# trees with the same name and the same 2W+2E shape, so the state
26+
# transitions and the --ignore variants map 1:1 between the two suites.
27+
# The exact warning/error strings are daemon-specific (bridge-nf-call
28+
# for docker, cgroup v1 for podman) because they reflect real stderr
29+
# output admins would see in production.
2030
TESTS = [
2131
{
22-
'id': 'crit-server-with-errors',
23-
'test': 'stdout/server-with-errors,stderr/STDERR01,0',
32+
'id': 'ok-no-stderr',
33+
'test': 'stdout/seven-containers-mixed-state,,0',
34+
'assert-retc': STATE_OK,
35+
'assert-in': [
36+
'7 Containers (2 running, 0 paused, 5 stopped)',
37+
'5 Images',
38+
'Storage Driver: overlay2',
39+
],
40+
},
41+
{
42+
'id': 'crit-stderr-warnings-and-errors',
43+
'test': 'stdout/seven-containers-mixed-state,stderr/two-warnings-two-errors,0',
2444
'assert-retc': STATE_CRIT,
2545
'assert-in': [
26-
'ERROR: an error happened, ERROR: invalid empty security option, '
27-
'WARNING: bridge-nf-call-iptables is disabled, '
28-
'WARNING: bridge-nf-call-ip6tables is disabled',
29-
'7 Containers (2 running, 0 paused, 5 stopped), '
30-
'5 Images, Storage Driver: overlay2',
46+
'ERROR: an error happened',
47+
'ERROR: invalid empty security option',
48+
'WARNING: bridge-nf-call-iptables',
49+
'WARNING: bridge-nf-call-ip6tables',
50+
'7 Containers (2 running, 0 paused, 5 stopped)',
3151
],
3252
},
53+
{
54+
'id': 'crit-ignore-warnings-only',
55+
'test': 'stdout/seven-containers-mixed-state,stderr/two-warnings-two-errors,0',
56+
# Filter out both WARNINGs; the two ERRORs remain and still
57+
# drive the overall state to CRIT.
58+
'params': "--ignore='^WARNING:'",
59+
'assert-retc': STATE_CRIT,
60+
'assert-in': ['ERROR: an error happened'],
61+
'assert-not-in': ['WARNING:'],
62+
},
63+
{
64+
'id': 'ok-ignore-all-stderr',
65+
'test': 'stdout/seven-containers-mixed-state,stderr/two-warnings-two-errors,0',
66+
'params': "--ignore='^WARNING:' --ignore='^ERROR:'",
67+
'assert-retc': STATE_OK,
68+
'assert-in': ['7 Containers'],
69+
'assert-not-in': ['WARNING:', 'ERROR:'],
70+
},
71+
{
72+
'id': 'crit-ignore-case-sensitive-default',
73+
'test': 'stdout/seven-containers-mixed-state,stderr/two-warnings-two-errors,0',
74+
# Uppercase pattern must NOT match a mixed-case stderr line:
75+
# the regex default is case-sensitive, so the ignore is a
76+
# no-op and the check stays CRIT.
77+
'params': "--ignore='BRIDGE-NF-CALL'",
78+
'assert-retc': STATE_CRIT,
79+
'assert-in': ['WARNING: bridge-nf-call-iptables'],
80+
},
81+
{
82+
'id': 'warn-ignore-errors-case-insensitive-opt-in',
83+
'test': 'stdout/seven-containers-mixed-state,stderr/two-warnings-two-errors,0',
84+
# Opt into case-insensitive matching with `(?i)`: matches
85+
# `ERROR:` even though the pattern is lowercased. After
86+
# hiding the errors only the warnings remain, so the state
87+
# drops from CRIT to WARN.
88+
'params': "--ignore='(?i)^error:'",
89+
'assert-retc': STATE_WARN,
90+
'assert-in': ['WARNING: bridge-nf-call-iptables'],
91+
'assert-not-in': ['ERROR:'],
92+
},
93+
{
94+
'id': 'unknown-ignore-invalid-regex',
95+
'test': 'stdout/seven-containers-mixed-state,stderr/two-warnings-two-errors,0',
96+
'params': "--ignore='('",
97+
'assert-retc': STATE_UNKNOWN,
98+
'assert-in': ['Invalid regular expression'],
99+
},
33100
]
34101

35102

check-plugins/docker-info/unit-test/stderr/STDERR01 renamed to check-plugins/docker-info/unit-test/stderr/two-warnings-two-errors

File renamed without changes.

check-plugins/docker-info/unit-test/stdout/server-with-errors renamed to check-plugins/docker-info/unit-test/stdout/seven-containers-mixed-state

File renamed without changes.

check-plugins/podman-info/README.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,29 @@ Displays system-wide Podman information including container counts, image count,
3030
## Help
3131

3232
```text
33-
usage: podman-info [-h] [-V] [--always-ok] [--test TEST]
33+
usage: podman-info [-h] [-V] [--always-ok] [--ignore IGNORE] [--test TEST]
3434
3535
Displays system-wide Podman information including container counts, image
36-
count, storage driver, runtime version, available CPUs, and total memory. For
37-
Docker, use the docker-info check instead. Requires root or sudo.
36+
count, storage driver, runtime version, available CPUs, and total memory. Also
37+
monitors the Podman daemon stderr for warnings and errors. Individual stderr
38+
lines can be filtered out with --ignore (e.g. benign cgroup warnings on
39+
rootless hosts). For Docker, use the docker-info check instead. Requires root
40+
or sudo.
3841
3942
options:
40-
-h, --help show this help message and exit
41-
-V, --version show program's version number and exit
42-
--always-ok Always returns OK.
43-
--test TEST For unit tests. Needs "path-to-stdout-file,path-to-stderr-
44-
file,expected-retc".
43+
-h, --help show this help message and exit
44+
-V, --version show program's version number and exit
45+
--always-ok Always returns OK.
46+
--ignore IGNORE Ignore stderr lines matching this Python regular
47+
expression. Case-sensitive by default; use `(?i)` for case-
48+
insensitive matching. Can be specified multiple times.
49+
Example: `--ignore="cgroup v1"` to suppress a benign
50+
cgroup-version warning on hosts that have not yet migrated
51+
to cgroup v2. Example: `--ignore="(?i)rootless"` (case-
52+
insensitive) to suppress any rootless-related informational
53+
warning. Default: None
54+
--test TEST For unit tests. Needs "path-to-stdout-file,path-to-stderr-
55+
file,expected-retc".
4556
```
4657

4758

check-plugins/podman-info/icingaweb2-module-director/podman-info.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"arguments": {
55
"--always-ok": {
66
"set_if": "$podman_info_always_ok$"
7+
},
8+
"--ignore": {
9+
"value": "$podman_info_ignore$",
10+
"repeat_key": true
711
}
812
},
913
"command": "/usr/bin/sudo /usr/lib64/nagios/plugins/podman-info",
@@ -13,6 +17,11 @@
1317
"datafield_id": 1,
1418
"is_required": "n",
1519
"var_filter": null
20+
},
21+
{
22+
"datafield_id": 2,
23+
"is_required": "n",
24+
"var_filter": null
1625
}
1726
],
1827
"imports": [],
@@ -67,7 +76,8 @@
6776
"use_var_overrides": null,
6877
"vars": {
6978
"criticality": "C",
70-
"podman_info_always_ok": false
79+
"podman_info_always_ok": false,
80+
"podman_info_ignore": []
7181
},
7282
"volatile": null,
7383
"zone": null,
@@ -83,6 +93,17 @@
8393
"format": null,
8494
"settings": {},
8595
"uuid": "bab2f8e7-6496-4b71-8f2c-06eb6840b6b0"
96+
},
97+
"2": {
98+
"varname": "podman_info_ignore",
99+
"caption": "Podman Info: Ignore",
100+
"description": "Ignore stderr lines matching this Python regular expression. Case-sensitive by default; use `(?i)` for case-insensitive matching. Can be specified multiple times.",
101+
"datatype": "Icinga\\Module\\Director\\DataType\\DataTypeArray",
102+
"format": null,
103+
"settings": {
104+
"visibility": "visible"
105+
},
106+
"uuid": "96a363d6-0b4a-4fd0-b521-48310425c78e"
86107
}
87108
}
88109
}

0 commit comments

Comments
 (0)