Skip to content

Commit 5eb08ea

Browse files
committed
fix(test): unblock cpu-usage and rpm-updates unit tests (#1071, #1072)
Both tests failed for environment reasons, not plugin regressions, and blocked the full unit test suite on tox runs. - cpu-usage: the regex `\d+\.\d+% -.* user:` assumed `user:` was always on the first output line, but when several CPU counters read `0.0%` the plugin's by-value sort is non-deterministic and `user:` can land on the second line. Relax to `(?s)\d+\.\d+%.*user:` so both layouts pass. - rpm-updates: add a `--test` argument that replaces the three underlying `yum` calls (`list --upgrades`, `list --installed`, `updateinfo list --available`) with stdout fixtures. The unit test is now fixture-based, covers ok-no-updates / warn-pending / ok-pending-with-high-warn, and runs in ~0.2s instead of ~2 minutes. The test no longer depends on the RHEL8 test container's upstream mirror state (there was a pending `vim-minimal` upgrade in the container that made the assertion `No updates available` flip over time). The existing `containerfiles/` dir stays for a future testcontainers migration. - tools/run-unit-tests: detect container-based tests by inspecting the `run` file for `podman` / `testcontainers` references instead of just checking for a `containerfiles/` dir. rpm-updates keeps its legacy containerfiles while its active `run` file is already fixture-based and fast.
1 parent 75daf26 commit 5eb08ea

File tree

9 files changed

+104
-232
lines changed

9 files changed

+104
-232
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212

1313
* `.github/workflows/docs.yml`: pin all GitHub Actions by commit SHA (with the version as a trailing comment) instead of by tag, clearing the four OpenSSF Scorecard `PinnedDependenciesID` alerts. Dependabot is already configured for `github-actions` and updates hash-pinned actions natively
1414
* axenita-stats: fix the version-number extraction slice `[8 : 8 + find('-') - 1]` that only worked for exactly 6-character versions like `14.0.8` and silently truncated any longer patch number. Use `split('-')[1]` instead, which handles `14.0.12`, `1.2.3`, and 2-digit majors correctly ([#1070](https://github.com/Linuxfabrik/monitoring-plugins/issues/1070))
15+
* cpu-usage: relax the unit test regex from `\d+\.\d+% -.* user:` to `(?s)\d+\.\d+%.*user:`. The old pattern assumed `user:` was always on the first output line, but when multiple CPU counters read `0.0%` the plugin's by-value sort is non-deterministic and `user:` can land on the second line. The new pattern accepts either layout ([#1071](https://github.com/Linuxfabrik/monitoring-plugins/issues/1071))
1516
* deb-updates: add missing `lib.txt` import so the "N update(s) available" summary no longer crashes with `AttributeError` at runtime
1617
* Fix `--require-hashes` pip install in pre-commit autoupdate workflow by using pinned version instead
1718
* fortios-network-io: make the "no warnings vs warnings present" branches structurally exclusive via an explicit `else:`. The old code relied on `lib.base.oao()` exiting to skip the follow-up call, which works but is fragile to read ([#1070](https://github.com/Linuxfabrik/monitoring-plugins/issues/1070))
@@ -31,9 +32,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3132
* qts-temperatures: the `systemp` and `cputemp` perfdata entries had their `warn` / `crit` thresholds swapped (system perfdata used the CPU threshold fields and vice versa). The message text was already correct ([#1070](https://github.com/Linuxfabrik/monitoring-plugins/issues/1070))
3233
* redis-status, valkey-status: the `key_count` perfdata value used the loop variable `keys` (the last database's per-DB key count) instead of the accumulated `key_count` (total across all databases). The "with X keys" message text was already using `key_count` ([#1070](https://github.com/Linuxfabrik/monitoring-plugins/issues/1070))
3334
* rocketchat-stats: add missing `lib.txt` import so the user-count pluralization no longer crashes with `AttributeError` at runtime
35+
* rpm-updates: add a `--test` argument that replaces the three underlying `yum` calls with stdout fixtures (`<base>-upgrades`, `<base>-installed`, `<base>-updateinfo`). The unit test is now fixture-based, covers ok-no-updates / warn-pending / ok-pending-with-high-warn, and runs in ~0.2s instead of ~2 minutes. No longer depends on the RHEL8 test container's upstream-mirror state ([#1072](https://github.com/Linuxfabrik/monitoring-plugins/issues/1072))
3436
* sap-open-concur-com: `choices=services.append('All')` was effectively `choices=None` because `list.append()` returns `None`. The `--service` argument therefore accepted any value without validation. Use `choices=services + ['All']` to build a proper choices list ([#1070](https://github.com/Linuxfabrik/monitoring-plugins/issues/1070))
3537
* starface-java-memory-usage: the heap and non-heap state checks used `state += lib.base.get_worst(used_state, state)` which adds state integers together and corrupts the accumulated state (e.g. WARN+WARN=2 reads as CRIT, WARN+CRIT=3 is outside the valid range). Replaced with `state = lib.base.get_worst(state, used_state)` so the accumulated state remains a valid STATE_OK / STATE_WARN / STATE_CRIT value ([#1070](https://github.com/Linuxfabrik/monitoring-plugins/issues/1070))
3638
* tools/run-unit-tests: add `--no-container` and `--only-container` flags so container-backed unit tests (podman-driven integration suites that take minutes per plugin) can be filtered out of the fast default run. `tools/run-container-tests` is a thin wrapper around `--only-container` for the full integration sweep. `tox` now invokes `tools/run-unit-tests --no-container` so the multi-Python matrix actually completes instead of hanging / OOM-killing on the first container stage
39+
* tools/run-unit-tests: classify a plugin as container-based by inspecting its `run` file for `podman` / `testcontainers` references instead of just checking for a `containerfiles/` subdirectory. This lets a plugin keep its legacy containerfiles around for a future testcontainers migration while its active `run` file is already fixture-based and fast
3740
* tools/run-unit-tests: skip the `example` plugin in default runs. Its unit test is a template meant to be copy-pasted into new plugins and does not correspond to a real check. Explicit `python tools/run-unit-tests example` still runs it
3841
* tox.ini: disable the sdist build (`no_package = true`) so `tox` no longer trips over the flat top-level layout with "Multiple top-level packages discovered". The repo is a collection of plugin scripts, not a Python package
3942
* tuned-profile, crypto-policy: make the "expected vs actual" branches structurally exclusive via an explicit `else:`. The old code relied on `lib.base.oao()` exiting to skip the follow-up WARN call, which works but is fragile to read ([#1070](https://github.com/Linuxfabrik/monitoring-plugins/issues/1070))

check-plugins/cpu-usage/unit-test/run

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ TESTS = [
2727
{
2828
'run-where': 'container', # vs. 'localhost'
2929
'plugin-params': '',
30-
'assert-regex': r'\d+\.\d+% -.* user:',
30+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
3131
'assert-retc': 0,
3232
},
3333
],
@@ -39,7 +39,7 @@ TESTS = [
3939
{
4040
'run-where': 'container',
4141
'plugin-params': '',
42-
'assert-regex': r'\d+\.\d+% -.* user:',
42+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
4343
'assert-retc': 0,
4444
},
4545
],
@@ -51,7 +51,7 @@ TESTS = [
5151
{
5252
'run-where': 'container',
5353
'plugin-params': '',
54-
'assert-regex': r'\d+\.\d+% -.* user:',
54+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
5555
'assert-retc': 0,
5656
},
5757
],
@@ -63,7 +63,7 @@ TESTS = [
6363
{
6464
'run-where': 'container',
6565
'plugin-params': '',
66-
'assert-regex': r'\d+\.\d+% -.* user:',
66+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
6767
'assert-retc': 0,
6868
},
6969
],
@@ -75,7 +75,7 @@ TESTS = [
7575
{
7676
'run-where': 'container',
7777
'plugin-params': '',
78-
'assert-regex': r'\d+\.\d+% -.* user:',
78+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
7979
'assert-retc': 0,
8080
},
8181
],
@@ -87,7 +87,7 @@ TESTS = [
8787
{
8888
'run-where': 'container',
8989
'plugin-params': '',
90-
'assert-regex': r'\d+\.\d+% -.* user:',
90+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
9191
'assert-retc': 0,
9292
},
9393
],
@@ -99,7 +99,7 @@ TESTS = [
9999
{
100100
'run-where': 'container',
101101
'plugin-params': '',
102-
'assert-regex': r'\d+\.\d+% -.* user:',
102+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
103103
'assert-retc': 0,
104104
},
105105
],
@@ -111,7 +111,7 @@ TESTS = [
111111
{
112112
'run-where': 'container',
113113
'plugin-params': '',
114-
'assert-regex': r'\d+\.\d+% -.* user:',
114+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
115115
'assert-retc': 0,
116116
},
117117
],
@@ -123,7 +123,7 @@ TESTS = [
123123
{
124124
'run-where': 'container',
125125
'plugin-params': '',
126-
'assert-regex': r'\d+\.\d+% -.* user:',
126+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
127127
'assert-retc': 0,
128128
},
129129
],
@@ -135,7 +135,7 @@ TESTS = [
135135
{
136136
'run-where': 'container',
137137
'plugin-params': '',
138-
'assert-regex': r'\d+\.\d+% -.* user:',
138+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
139139
'assert-retc': 0,
140140
},
141141
],
@@ -147,7 +147,7 @@ TESTS = [
147147
{
148148
'run-where': 'container',
149149
'plugin-params': '',
150-
'assert-regex': r'\d+\.\d+% -.* user:',
150+
'assert-regex': r'(?s)\d+\.\d+%.*user:',
151151
'assert-retc': 0,
152152
},
153153
],

check-plugins/rpm-updates/rpm-updates

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ from lib.globals import STATE_OK, STATE_UNKNOWN
2424

2525

2626
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
27-
__version__ = '2025100601'
27+
__version__ = '2026041201'
2828

2929
DESCRIPTION = """Checks for available RPM package updates on RHEL, CentOS, Fedora, and compatible
3030
systems. Reports the number and type of available advisories (bugfix, enhancement,
@@ -75,6 +75,13 @@ def parse_args():
7575
default=DEFAULT_QUERY,
7676
)
7777

78+
parser.add_argument(
79+
'--test',
80+
help=lib.args.help('--test'),
81+
dest='TEST',
82+
type=lib.args.csv,
83+
)
84+
7885
parser.add_argument(
7986
'--timeout',
8087
help=lib.args.help('--timeout') + ' Default: %(default)s (seconds)',
@@ -138,19 +145,29 @@ def get_updates(args):
138145
- Intended for use within a script or plugin’s `main()` function.
139146
"""
140147
# get the list of updates (--assumeyes so command can import GPG keys)
141-
yum_upgrades, stderr, retc = lib.base.coe(
142-
lib.shell.shell_exec('yum list --assumeyes --upgrades', timeout=args.TIMEOUT),
143-
)
148+
if args.TEST is None:
149+
yum_upgrades, stderr, retc = lib.base.coe(
150+
lib.shell.shell_exec('yum list --assumeyes --upgrades', timeout=args.TIMEOUT),
151+
)
152+
else:
153+
yum_upgrades, stderr, retc = lib.lftest.test(
154+
[args.TEST[0] + '-upgrades', args.TEST[1], args.TEST[2]],
155+
)
144156
if retc:
145157
lib.base.cu(f'`yum list --upgrades` returned with error {retc}: {stderr}')
146158
if not yum_upgrades:
147159
# no updates available
148160
lib.base.oao('No updates available.')
149161

150162
# get the list of installed software
151-
yum_installed, stderr, retc = lib.base.coe(
152-
lib.shell.shell_exec('yum list --installed', timeout=args.TIMEOUT),
153-
)
163+
if args.TEST is None:
164+
yum_installed, stderr, retc = lib.base.coe(
165+
lib.shell.shell_exec('yum list --installed', timeout=args.TIMEOUT),
166+
)
167+
else:
168+
yum_installed, stderr, retc = lib.lftest.test(
169+
[args.TEST[0] + '-installed', args.TEST[1], args.TEST[2]],
170+
)
154171
if retc or stderr:
155172
lib.base.cu(f'`yum list --installed` returned with error {retc}: {stderr}')
156173

@@ -204,9 +221,14 @@ def get_updateinfo(args):
204221
# Name Type Severity Package Issued
205222
# FEDORA-2025-09f40d bugfix Low python3-boto3-1.38.23-1.fc42.noarch 2025-05-30 01:14:13
206223
# FEDORA-2025-34e9b9 security Critical firefox-139.0-1.fc42.x86_64 2025-05-30 02:21:33
207-
yum_info, stderr, retc = lib.base.coe(
208-
lib.shell.shell_exec('yum updateinfo list --available', timeout=args.TIMEOUT),
209-
)
224+
if args.TEST is None:
225+
yum_info, stderr, retc = lib.base.coe(
226+
lib.shell.shell_exec('yum updateinfo list --available', timeout=args.TIMEOUT),
227+
)
228+
else:
229+
yum_info, stderr, retc = lib.lftest.test(
230+
[args.TEST[0] + '-updateinfo', args.TEST[1], args.TEST[2]],
231+
)
210232
if retc:
211233
lib.base.cu(
212234
f'`yum updateinfo list --available` returned with error {retc}: {stderr}'

0 commit comments

Comments
 (0)