Skip to content

Commit

Permalink
Parse command as a single long string.
Browse files Browse the repository at this point in the history
  • Loading branch information
johanthoren committed Oct 8, 2024
1 parent c9d97cb commit b44a43f
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 33 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,19 @@ It's a naive implementation, use with caution. Special cases are not handled.
## Usage

``` shell
usage: check_with_thresholds_as_perfdata.py [-h] [-w WARNING] [-c CRITICAL]
...
usage: check_with_thresholds_as_perfdata.py [-h] [-w WARNING] [-c CRITICAL] -C COMMAND

Opsview Plugin Wrapper Script

positional arguments:
command Command to execute

options:
-h, --help show this help message and exit
-w WARNING, --warning WARNING
Warning threshold
-c CRITICAL, --critical CRITICAL
Critical threshold
-C COMMAND, --command COMMAND
Command to execute

```

* Each threshold is optional, but at least one must be provided.
Expand All @@ -30,11 +29,12 @@ options:
* Perfdata metrics will be sorted in the output.
* The return code of the executed command will be passed through.
* Exceptions will be caught and the return code will be 3 (UNKNOWN).
* The COMMAND should be surrounded by double quotes.

## Example

``` shell
$ ./check_with_thresholds_as_perfdata.py -w 80 -c 90 /bin/echo "OK - Everything is fine | metric=1;2;3;4"
$ ./check_with_thresholds_as_perfdata.py -w 80 -c 90 -C "/bin/echo 'OK - Everything is fine | metric=1;2;3;4'"
OK - Everything is fine | metric_critical=90;;;4 metric_warning=80;;;4 metric=1;2;3;4
```

Expand Down
27 changes: 15 additions & 12 deletions check_with_thresholds_as_perfdata.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/opt/opsview/python3/bin/python
#
# Copyright 2024 ITRS Group Ltd.
#
Expand Down Expand Up @@ -27,18 +27,20 @@ def parse_arguments():
parser = argparse.ArgumentParser(description="Opsview Plugin Wrapper Script")
parser.add_argument("-w", "--warning", type=str, help="Warning threshold")
parser.add_argument("-c", "--critical", type=str, help="Critical threshold")
parser.add_argument("command", nargs=argparse.REMAINDER, help="Command to execute")
args = parser.parse_args()
if not args.command:
sys.stderr.write("Error: No command provided to execute\n")
sys.exit(3)
return args
parser.add_argument("-C", "--command", help="Command to execute", type=str, required=True)

return parser.parse_args()


def execute_command(command):
"""Execute the command and return the result."""
if command.startswith('"') and command.endswith('"'):
command = command[1:-1]
elif command.startswith("'") and command.endswith("'"):
command = command[1:-1]

try:
result = subprocess.run(shlex.split(command), capture_output=True, text=True, check=False)
result = subprocess.run(command, capture_output=True, text=True, check=False, shell=True)
except FileNotFoundError:
sys.stderr.write(f"Error: Command not found: {command}\n")
sys.exit(127)
Expand All @@ -51,7 +53,8 @@ def execute_command(command):

def process_command_output(result):
"""Process the command output and return stdout, stderr, and return code."""
if result.returncode > 3:
if result.returncode > 2:
print(result.stdout)
sys.stderr.write(result.stderr)
sys.exit(result.returncode)
return result.stdout.strip(), result.stderr.strip(), result.returncode
Expand Down Expand Up @@ -154,13 +157,13 @@ def main():
sys.stderr.write("Error: --warning and/or --critical must be provided\n")
sys.exit(3)

command = " ".join(args.command).strip()
result = execute_command(command)
result = execute_command(args.command)
stdout, stderr, return_code = process_command_output(result)
output, perfdata = extract_perfdata(stdout)

if not perfdata:
sys.stderr.write("Error: No performance data found\n")
sys.stderr.write("Error: No performance data found. Got the following output:\n")
sys.stderr.write(stdout + "\n")
sys.exit(3)

perfdata_entries = parse_perfdata(perfdata)
Expand Down
63 changes: 48 additions & 15 deletions tests/test_check_with_thresholds_as_perfdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,57 @@
from io import StringIO

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from check_with_thresholds_as_perfdata import main, append_thresholds_to_perfdata, parse_perfdata
from check_with_thresholds_as_perfdata import (
main,
append_thresholds_to_perfdata,
parse_arguments,
parse_perfdata,
)

OK_OUTPUT = "OK - Disk space is sufficient | '/var'=55%;80;90;0;100"
WARNING_OUTPUT = "WARNING - Disk space is NOT sufficient | '/var'=85%;80;90;0;100"
CRITICAL_OUTPUT = "CRITICAL - Disk space is NOT sufficient | '/var'=95%;80;90;0;100"
SINGLE_PART_CMD_LINE_ARGS = [
"/opt/opsview/monitoringscripts/plugins/check_nrpe",
"-H",
"192.168.1.1",
"-c",
"linux_stat",
"-a",
"-D -w 80 -c 90 -p /var -u %",
"-C",
(
"/opt/opsview/monitoringscripts/plugins/check_nrpe"
"-H"
"192.168.1.1"
"-c"
"linux_stat"
"-a"
"-D -w 80 -c 90 -p /var -u %"
),
]
DUAL_PART_CMD_LINE_ARGS = SINGLE_PART_CMD_LINE_ARGS[:-1] + ["-D -w 80 -c 90 -p /tmp -p /var -u %"]
TRIPLE_PART_CMD_LINE_ARGS = SINGLE_PART_CMD_LINE_ARGS[:-1] + [
"-D -w 80 -c 90 -p /tmp -p /var -p / -u %"
DUAL_PART_CMD_LINE_ARGS = [
"-C",
(
"/opt/opsview/monitoringscripts/plugins/check_nrpe"
"-H"
"192.168.1.1"
"-c"
"linux_stat"
"-a"
"-D -w 80 -c 90 -p /tmp -p /var -u %"
),
]

TRIPLE_PART_CMD_LINE_ARGS = [
"-C",
(
"/opt/opsview/monitoringscripts/plugins/check_nrpe"
"-H"
"192.168.1.1"
"-c"
"linux_stat"
"-a"
"-D -w 80 -c 90 -p /tmp -p /var -p / -u %"
),
]


class TestOpsviewPluginWrapper(unittest.TestCase):

def test_append_thresholds_to_perfdata(self):
perfdata_entries = parse_perfdata("'/var'=55%;80;90;0;100")
updated_perfdata = append_thresholds_to_perfdata(
Expand Down Expand Up @@ -90,9 +120,8 @@ def test_command_not_found(self, mock_subprocess_run, _mock_stderr):
"80",
"-c",
"90",
"/bin/foo",
"-H",
"localhost",
"-C",
"/bin/foo -H localhost",
]
with patch.object(sys, "argv", test_args):
try:
Expand Down Expand Up @@ -128,7 +157,11 @@ def test_invalid_command_without_perfdata(self, mock_subprocess_run, _mock_stdou
except SystemExit as e:
self.assertEqual(e.code, 3)

expected_output = "Error: No performance data found\n"
expected_output = (
"Error: No performance data found. "
"Got the following output:\n"
"OK - Disk space is sufficient\n"
)
self.assertEqual(expected_output, mock_stderr.getvalue())

@patch("sys.stderr", new_callable=StringIO)
Expand Down

0 comments on commit b44a43f

Please sign in to comment.