From 4f1a6a6c87dc4b061da27ef3eced888ae9d18bae Mon Sep 17 00:00:00 2001 From: Adar Nimrod Date: Sun, 25 Jul 2021 21:09:43 +0300 Subject: [PATCH] Progress. - More tests, now using mocks. - Silence some linter warnings. - Start thinking about parsing perfdata. --- .pre-commit-config.yaml | 1 + mnpw/__init__.py | 1 + mnpw/nagios.py | 17 ++++++++--- tests/test_nagios.py | 63 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b6e31d..a34e44d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,6 +62,7 @@ repos: additional_dependencies: - bandit - pyroma + exclude: ^tests/.* - repo: https://gitlab.com/pycqa/flake8.git rev: 3.9.2 diff --git a/mnpw/__init__.py b/mnpw/__init__.py index 2b0fc95..abd3f75 100644 --- a/mnpw/__init__.py +++ b/mnpw/__init__.py @@ -1,4 +1,5 @@ """My Nagios plugin wrapper.""" +# pylint: disable=logging-fstring-interpolation __version__ = "0.1.0" import argparse diff --git a/mnpw/nagios.py b/mnpw/nagios.py index 01246b7..a518d9b 100644 --- a/mnpw/nagios.py +++ b/mnpw/nagios.py @@ -1,11 +1,14 @@ """Nagios check implementation. Based on the specification from -https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/3/en/pluginapi.html""" +https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/3/en/pluginapi.html +""" +# pylint: disable=logging-fstring-interpolation +import collections import enum import logging -import subprocess +import subprocess # nosec DEFAULT_TIMEOUT = 10 # In seconds. @@ -19,7 +22,13 @@ class NagiosCode(enum.IntEnum): UNKNOWN = 3 +PerfData = collections.namedtuple( + "PerfData", ["name", "value", "unit", "warning", "critical", "min", "max"] +) + + class Check: + # pylint: disable=invalid-name """Nagios check using a plugin.""" Command = None @@ -32,7 +41,7 @@ class Check: stderr = None _stdout = None - def __init__(self, command, args): + def __init__(self, command, args=None): if not command: raise ValueError("Command is empty.") self.Command = command @@ -55,7 +64,7 @@ class Check: ] + self.Arguments logging.info(f"Running command {_cmd}.") try: - proc = subprocess.run( + proc = subprocess.run( # nosec [ self.Command, ] diff --git a/tests/test_nagios.py b/tests/test_nagios.py index 2e5a883..2483c6e 100644 --- a/tests/test_nagios.py +++ b/tests/test_nagios.py @@ -1,7 +1,24 @@ +import subprocess +import unittest.mock + import pytest from mnpw import nagios +OUTPUT_1 = """DISK OK - free space: / 3326 MB (56%);""" +OUTPUT_2 = ( + """ DISK OK - free space: / 3326 MB (56%); | /=2643MB;5948;5958;0;5968""" +) +OUTPUT_3 = """\ +DISK OK - free space: / 3326 MB (56%); | /=2643MB;5948;5958;0;5968 +/ 15272 MB (77%); +/boot 68 MB (69%); +/home 69357 MB (27%); +/var/log 819 MB (84%); | /boot=68MB;88;93;0;98 +/home=69357MB;253404;253409;0;253414 +/var/log=818MB;970;975;0;980 +""" + @pytest.mark.parametrize( "command,args,exit_code", @@ -30,4 +47,48 @@ def test_check_timeout(): """Test check with a timed out command.""" check = nagios.Check("sleep", ["20"]) with pytest.raises(RuntimeError): - check.run(3) + check.run(timeout=3) + + +def _mock_run(*args, **kwargs): + """Mock subprocess' run.""" + return unittest.mock.patch.object( + nagios.subprocess, + "run", + *args, + **kwargs, + ) + + +@pytest.mark.parametrize( + "exception", + [ + FileNotFoundError, + subprocess.TimeoutExpired(cmd="true", timeout=nagios.DEFAULT_TIMEOUT), + ], +) +def test_check_exceptions(exception): + """Test handling of subprocess' run exceptions. + See + https://docs.python.org/3/library/subprocess.html?highlight=popen#subprocess.SubprocessError + """ + check = nagios.Check("true") + with _mock_run(side_effect=exception), pytest.raises(RuntimeError): + check.run() + + +@pytest.mark.parametrize("output", [OUTPUT_1, OUTPUT_2, OUTPUT_3]) +def test_output_parsing(output): + """Test parsing of plugin output.""" + check = nagios.Check("true") + proc = subprocess.CompletedProcess( + [ + "true", + ], + 0, + output, + "", + ) + with _mock_run(return_value=proc): + check.run() + # TODO: validate something. -- GitLab