15 Commits

Author SHA1 Message Date
Markus Opolka
dfcdf4d872 Rework JsonHelper.get() to work with bracket in keys 2024-03-22 16:19:43 +01:00
Markus Opolka
ce9c5fdada Merge pull request #85 from drewkerrigan/extend-tests
Extend tests for array syntax
2024-03-22 15:52:10 +01:00
Markus Opolka
27c710b2ea Extend tests for array syntax 2024-03-22 15:45:25 +01:00
Markus Opolka
dddf8432d6 Merge pull request #80 from mho21/master
disabled check_hostname to prevent error message when setting CERT_NONE
2022-10-04 16:26:06 +02:00
Markus Hof
739c093702 disabled check_hostname to prevent error message when setting CERT_NONE 2022-10-04 16:04:12 +02:00
Markus Opolka
46271c961b Bump version to 2.1.2 2022-09-15 15:25:38 +02:00
Markus Opolka
49b338bdb6 Merge pull request #79 from drewkerrigan/feature/http-method
Add CLI Flag to change HTTP method
2022-09-15 15:22:48 +02:00
Markus Opolka
9f41fc491e Add CLI flag to change HTTP method 2022-09-09 17:28:35 +02:00
Markus Opolka
3a22b712ab Fix deprecation of PROTOCOL_TLS 2022-09-09 17:26:23 +02:00
Markus Opolka
9626fc4464 Merge pull request #78 from drewkerrigan/docs/update-repo
Update Makefile and Workflows
2022-09-08 10:09:43 +02:00
Markus Opolka
c54a0040a0 Update pylint config 2022-09-08 10:08:39 +02:00
Markus Opolka
ffd96dd59f Update GitHub Workflow 2022-09-08 10:04:20 +02:00
Markus Opolka
0572c2f494 Update Makefile
- Use python from venv
2022-09-08 10:01:23 +02:00
Markus Opolka
2e6eaeea59 Merge pull request #77 from K0nne/patch-1
fix missing type conversion for --data
2022-09-08 09:59:28 +02:00
K0nne
428a5a6d3a fix missing type conversion for --data
The parameter --data is handled as type string, but the method urlopen() only accepts the datatype byte.
Before this fix you will get: "TypeError: POST data should be  bytes, an iterable of bytes, or a filer object. It cannot be of type str."
This PR solves this.
2022-07-27 13:30:25 +02:00
8 changed files with 104 additions and 39 deletions

View File

@@ -7,21 +7,20 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8]
python-version: [3.8, 3,9]
name: GitHub Action
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install dependencies
run: |
python -m pip install -r requirements-dev.txt
- name: Lint
run: |
pip3 install --upgrade pip wheel setuptools
pip3 install pylint
python3 -m pylint check_http_json.py
make lint
- name: Unit Test
run: |
python3 -m unittest discover
make test
- name: Coverage
run: |
pip3 install coverage
python3 -m coverage run -m unittest discover
python3 -m coverage report -m --include check_http_json.py
make coverage

View File

@@ -1,5 +1,21 @@
# pylint config
[MESSAGES CONTROL]
disable=line-too-long, redefined-outer-name, too-many-arguments, too-many-instance-attributes, fixme, invalid-name, superfluous-parens, missing-function-docstring, missing-module-docstring, multiple-imports, no-else-return, too-many-return-statements, too-many-branches, too-many-statements
[MASTER]
ignore-patterns=^test.*
[MESSAGES CONTROL]
disable=fixme,
consider-using-f-string,
invalid-name,
line-too-long,
missing-function-docstring,
missing-module-docstring,
multiple-imports,
no-else-return,
redefined-outer-name,
superfluous-parens,
too-many-locals,
too-many-arguments,
too-many-branches,
too-many-instance-attributes,
too-many-return-statements,
too-many-statements

9
Makefile Normal file
View File

@@ -0,0 +1,9 @@
.PHONY: lint test coverage
lint:
python -m pylint check_http_json.py
test:
python -m unittest discover
coverage:
python -m coverage run -m unittest discover
python -m coverage report -m --include check_http_json.py

View File

@@ -38,7 +38,7 @@ Generic Nagios plugin which checks json values from a given endpoint against
argument specified rules and determines the status and performance data for
that service.
Version: 2.0.0 (2020-03-22)
Version: 2.1.2 (2022-09-15)
optional arguments:
-h, --help show this help message and exit
@@ -46,6 +46,8 @@ optional arguments:
-s, --ssl use TLS to connect to remote host
-H HOST, --host HOST remote host to query
-k, --insecure do not check server SSL certificate
-X {GET,POST}, --request {GET,POST}
Specifies a custom request method to use when communicating with the HTTP server
-V, --version print version of this plugin
--cacert CACERT SSL CA certificate
--cert CERT SSL client certificate

View File

@@ -24,8 +24,8 @@ WARNING_CODE = 1
CRITICAL_CODE = 2
UNKNOWN_CODE = 3
__version__ = '2.0.0'
__version_date__ = '2020-03-22'
__version__ = '2.1.2'
__version_date__ = '2022-09-15'
class NagiosHelper:
"""
@@ -156,25 +156,30 @@ class JsonHelper:
data = temp_data
else:
data = self.data
if len(key) <= 0:
return data
if key.find(self.separator) != -1 and \
key.find(self.arrayOpener) != -1:
if key.find(self.separator) != -1 and key.find(self.arrayOpener) != -1:
if key.find(self.separator) < key.find(self.arrayOpener):
return self.getSubElement(key, data)
else:
return self.getSubArrayElement(key, data)
else:
if key.find(self.separator) != -1:
return self.getSubElement(key, data)
else:
if key.find(self.arrayOpener) != -1:
return self.getSubArrayElement(key, data)
else:
if isinstance(data, dict) and key in data:
return data[key]
else:
return (None, 'not_found')
if key.find(self.separator) != -1:
return self.getSubElement(key, data)
if key.find(self.arrayOpener) != -1:
# If we got an arrayOpener but the next char is not [0-9] or * then it might just be a string
# This isn't optimal since this 'update (foobar)(0)' still won't work
if key[key.find(self.arrayOpener)+1].isnumeric() or key[key.find(self.arrayOpener)+1] == "*":
return self.getSubArrayElement(key, data)
if isinstance(data, dict) and key in data:
return data[key]
return (None, 'not_found')
def expandKey(self, key, keys):
if '(*)' not in key:
@@ -430,6 +435,8 @@ def parseArgs(args):
help='remote host to query')
parser.add_argument('-k', '--insecure', action='store_true',
help='do not check server SSL certificate')
parser.add_argument('-X', '--request', dest='method', default='GET', choices=['GET', 'POST'],
help='Specifies a custom request method to use when communicating with the HTTP server')
parser.add_argument('-V', '--version', action='store_true',
help='print version of this plugin')
parser.add_argument('--cacert',
@@ -542,11 +549,12 @@ def main(cliargs):
if args.ssl:
url = "https://%s" % args.host
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.options |= ssl.OP_NO_SSLv2
context.options |= ssl.OP_NO_SSLv3
if args.insecure:
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
else:
context.verify_mode = ssl.CERT_OPTIONAL
@@ -587,7 +595,7 @@ def main(cliargs):
json_data = ''
try:
req = urllib.request.Request(url)
req = urllib.request.Request(url, method=args.method)
req.add_header("User-Agent", "check_http_json")
if args.auth:
authbytes = str(args.auth).encode()
@@ -599,14 +607,17 @@ def main(cliargs):
for header in headers:
req.add_header(header, headers[header])
if args.timeout and args.data:
databytes = str(args.data).encode()
response = urllib.request.urlopen(req, timeout=args.timeout,
data=args.data, context=context)
data=databytes, context=context)
elif args.timeout:
response = urllib.request.urlopen(req, timeout=args.timeout,
context=context)
elif args.data:
response = urllib.request.urlopen(req, data=args.data, context=context)
databytes = str(args.data).encode()
response = urllib.request.urlopen(req, data=databytes, context=context)
else:
# pylint: disable=consider-using-with
response = urllib.request.urlopen(req, context=context)
json_data = response.read()

View File

@@ -1,9 +0,0 @@
.PHONY: lint test coverage
lint:
python3 -m pylint check_http_json.py
test:
python3 -m unittest discover
coverage:
python3 -m coverage run -m unittest discover
python3 -m coverage report -m --include check_http_json.py

2
requirements-dev.txt Normal file
View File

@@ -0,0 +1,2 @@
coverage==6.4.4
pylint==2.15.2

View File

@@ -110,6 +110,14 @@ class UtilTest(unittest.TestCase):
self.check_data(RulesHelper().dash_U(['metric,0']),
'{"metric": 3}', UNKNOWN_CODE)
def test_array(self):
self.check_data(RulesHelper().dash_q(['foo(0),bar']),
'{"foo": ["bar"]}', OK_CODE)
self.check_data(RulesHelper().dash_q(['foo(0),foo']),
'{"foo": ["bar"]}', WARNING_CODE)
self.check_data(RulesHelper().dash_Q(['foo(1),bar']),
'{"foo": ["bar"]}', CRITICAL_CODE)
def test_exists(self):
self.check_data(RulesHelper().dash_e(['nothere']),
'{"metric": 5}', WARNING_CODE)
@@ -294,3 +302,30 @@ class UtilTest(unittest.TestCase):
# This should throw an error
data = '[]'
self.check_data(rules.dash_q(['(*).update_status,warn_me']), data, CRITICAL_CODE)
def test_bracket_in_key(self):
"""
https://github.com/drewkerrigan/nagios-http-json/issues/76
"""
rules = RulesHelper()
# This should work
data = '[{"update status": "failure"}]'
self.check_data(rules.dash_q(['(*).update status,failure']), data, OK_CODE)
data = '[{"update (status)": "failure"}]'
self.check_data(rules.dash_q(['(*).update (status),failure']), data, OK_CODE)
data = '[{"update (((status)": "failure"}]'
self.check_data(rules.dash_q(['(*).update (((status),failure']), data, OK_CODE)
data = '[{"update )status)": "failure"}]'
self.check_data(rules.dash_q(['(*).update )status),failure']), data, OK_CODE)
data = '[{"update (status": "failure"}]'
self.check_data(rules.dash_q(['(*).update (status),failure']), data, WARNING_CODE)
# Does not yet work
# data = '{"update (foobar)": ["bar"]}'
# self.check_data(rules.dash_q(['update (foobar)(0),bar']), data, OK_CODE)