diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 84f6c7bfacae235c908c603e1ea02f64ff5a6912..e5582169621ce6309ed68e9e1f18cf6ee64788c3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,3 +45,14 @@ run-executable: needs: - job: build-executable artifacts: true + +pytest: + extends: .python3 + stage: test + before_script: + - poetry install + script: + - poetry run pytest --junit-xml test.xml + artifacts: + reports: + junit: test.xml diff --git a/mnpw/__init__.py b/mnpw/__init__.py index 5c38cf9243fdbf495dc2433432047f176b21e5da..a20a024dbd7e9e59eaf21a5301d70940fce6e09f 100644 --- a/mnpw/__init__.py +++ b/mnpw/__init__.py @@ -52,7 +52,7 @@ def main(): check = nagios.Check(args.command, args.arguments) try: check.run(args.timeout, args.dry_run) - except Exception as ex: + except Exception as ex: # pylint: disable=broad-except parser.error(str(ex)) diff --git a/mnpw/nagios.py b/mnpw/nagios.py index d396c8e96c18fe90ca60fbab0524ebc92fd7176e..b263fdda266937054a9a25b52e664e3f2b5cf581 100644 --- a/mnpw/nagios.py +++ b/mnpw/nagios.py @@ -1,7 +1,10 @@ -"""Nagios check implementation.""" +"""Nagios check implementation. + +Based on the specification from +https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/3/en/pluginapi.html""" import enum -import subprocess +import subprocess # nosemgrep: rules.bandit.B404 DEFAULT_TIMEOUT = 10 # In seconds. @@ -21,11 +24,11 @@ class Check: Command = None Arguments = [] ExitCode = None - Result = None Output = None PerfData = None + LongOutput = None AdditionalOutput = None - StandardError = None + stderr = None def __init__(self, command, args): if not command: @@ -34,9 +37,16 @@ class Check: if args: self.Arguments = args - def run(self, timeout=DEFAULT_TIMEOUT, dryrun=False): + def _parse_output(self): + """Parses the plugin output to get the output, perf data and long + output. Can be run after the plugin has run and finished + successfully.""" + if self.ExitCode is None: + raise RuntimeError("Check hasn't run yet.") + + def run(self, timeout=DEFAULT_TIMEOUT): """Run the check (if it's hasn't run yet).""" - if self.Result is not None: + if self.ExitCode is not None: raise Exception("Check has already run.") try: proc = subprocess.run( @@ -53,3 +63,5 @@ class Check: raise RuntimeError(f"Command {self.Command} not found.") except subprocess.TimeoutExpired: raise RuntimeError("Timeout exceeded.") + self.ExitCode = proc.returncode + self.stderr = proc.stderr diff --git a/pyproject.toml b/pyproject.toml index 98e0fbf98172188c5af550aaf2b7d9d13b839dd8..4e121086ecbd23c5da5761005346767c15e8b184 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ requests = "^2.25.1" [tool.poetry.dev-dependencies] pre-commit = "^2.13.0" pyinstaller = "^4.3" +pytest = "^6.2.4" [tool.poetry.scripts] mnpw = "mnpw:main" diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/test_nagios.py b/tests/test_nagios.py new file mode 100644 index 0000000000000000000000000000000000000000..2e5a883533cc23ae0e254e2e8d226255f78577db --- /dev/null +++ b/tests/test_nagios.py @@ -0,0 +1,33 @@ +import pytest + +from mnpw import nagios + + +@pytest.mark.parametrize( + "command,args,exit_code", + [ + ("/bin/sh", ["-c", "exit 0"], nagios.NagiosCode.OK), + ("/bin/sh", ["-c", "exit 1"], nagios.NagiosCode.WARNING), + ("/bin/sh", ["-c", "exit 2"], nagios.NagiosCode.CRITICAL), + ("/bin/sh", ["-c", "exit 3"], nagios.NagiosCode.UNKNOWN), + ], +) +def test_check_exec(command, args, exit_code): + """Test the executation of checks.""" + check = nagios.Check(command, args) + check.run() + assert check.ExitCode == exit_code + + +def test_check_command_not_found(): + """Test check with a nonexistant command.""" + check = nagios.Check("/abcdef", []) + with pytest.raises(RuntimeError): + check.run() + + +def test_check_timeout(): + """Test check with a timed out command.""" + check = nagios.Check("sleep", ["20"]) + with pytest.raises(RuntimeError): + check.run(3)