dalibo / check_patroni

A nagios plugin for patroni.
PostgreSQL License
7 stars 3 forks source link

Command "node_is_alive" return python error #48

Closed leeroyke closed 1 year ago

leeroyke commented 1 year ago

Hello,

I use check_patroni on Debian 11 with python 3.9.2 and patroni 3.0.1, and i would like use the command "node_is_alive", but I return this python error, here is the command I use, in verbose mode :

# /usr/bin/check_patroni -vv -e http://127.0.0.1:8008 node_is_alive
NODEISALIVE UNKNOWN: AttributeError: module 'requests.exceptions' has no attribute 'JSONDecodeError'
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/check_patroni/types.py", line 73, in rest_api
    return r.json()
  File "/usr/lib/python3/dist-packages/requests/models.py", line 900, in json
    return complexjson.loads(self.text, **kwargs)
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nagiosplugin/runtime.py", line 44, in wrapper
    return func(*args, **kwds)
  File "/usr/lib/python3/dist-packages/check_patroni/cli.py", line 747, in node_is_alive
    check.main(verbose=ctx.obj.verbose, timeout=ctx.obj.timeout)
  File "/usr/lib/python3/dist-packages/nagiosplugin/check.py", line 121, in main
    runtime.execute(self, verbose, timeout)
  File "/usr/lib/python3/dist-packages/nagiosplugin/runtime.py", line 129, in execute
    with_timeout(self.timeout, self.run, check)
  File "/usr/lib/python3/dist-packages/nagiosplugin/platform/posix.py", line 17, in with_timeout
    func(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/nagiosplugin/runtime.py", line 118, in run
    check()
  File "/usr/lib/python3/dist-packages/nagiosplugin/check.py", line 106, in __call__
    self._evaluate_resource(resource)
  File "/usr/lib/python3/dist-packages/nagiosplugin/check.py", line 73, in _evaluate_resource
    metrics = resource.probe()
  File "/usr/lib/python3/dist-packages/check_patroni/node.py", line 251, in probe
    self.rest_api("liveness")
  File "/usr/lib/python3/dist-packages/check_patroni/types.py", line 74, in rest_api
    except requests.exceptions.JSONDecodeError:
AttributeError: module 'requests.exceptions' has no attribute 'JSONDecodeError'

Can you help me for this issues ? Thanks.

blogh commented 1 year ago

Hi, which version are you using ?

blogh commented 1 year ago

I spotted a similar problem in #31 and fixed it in v1. Are you using an older version ?

leeroyke commented 1 year ago

Hi, I use v1, we have create a debian package from this release : https://github.com/dalibo/check_patroni/releases/tag/v1.0.0

The debian package : https://packages.debian.org/sid/check-patroni

dlax commented 1 year ago

Can you try to apply this patch?

diff --git a/check_patroni/types.py b/check_patroni/types.py
index 16789a7..dd64905 100644
--- a/check_patroni/types.py
+++ b/check_patroni/types.py
@@ -8,7 +8,7 @@ import requests
 from . import _log

-class APIError(requests.exceptions.RequestException):
+class APIError(requests.RequestException):
     """This exception is raised when the rest api couldn't
     be reached and we got a http status code different from 200.
     """
@@ -71,7 +71,7 @@ class PatroniResource(nagiosplugin.Resource):

             try:
                 return r.json()
-            except requests.exceptions.JSONDecodeError:
+            except requests.JSONDecodeError:
                 return None
         raise nagiosplugin.CheckError("Connection failed for all provided endpoints")

@blogh, there is probably no need to pull exception classes from the requests.exceptions module as they are exposed at package-level and documented.

leeroyke commented 1 year ago

I apply this patch :

--- check_patroni_backup/types.py   2023-09-06 10:56:10.000000000 +0200
+++ /usr/lib/python3/dist-packages/check_patroni/types.py   2023-09-19 17:44:23.252305699 +0200
@@ -8,7 +8,7 @@
 from . import _log

-class APIError(requests.exceptions.RequestException):
+class APIError(requests.RequestException):
     """This exception is raised when the rest api couldn't
     be reached and we got a http status code different from 200.
     """
@@ -71,7 +71,7 @@

             try:
                 return r.json()
-            except requests.exceptions.JSONDecodeError:
+            except requests.JSONDecodeError:
                 return None
         raise nagiosplugin.CheckError("Connection failed for all provided endpoints")

But I have the same error like this :

~# /usr/bin/check_patroni -vvv node_is_alive
DEBUG - Trying to connect to http://127.0.0.1:8008/liveness with cert: None verify: None
DEBUG - Starting new HTTP connection (1): 127.0.0.1:8008
DEBUG - http://127.0.0.1:8008 "GET /liveness HTTP/1.1" 200 None
DEBUG - api call data: <Empty>
NODEISALIVE UNKNOWN: AttributeError: module 'requests' has no attribute 'JSONDecodeError'
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/check_patroni/types.py", line 73, in rest_api
    return r.json()
  File "/usr/lib/python3/dist-packages/requests/models.py", line 900, in json
    return complexjson.loads(self.text, **kwargs)
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nagiosplugin/runtime.py", line 44, in wrapper
    return func(*args, **kwds)
  File "/usr/lib/python3/dist-packages/check_patroni/cli.py", line 747, in node_is_alive
    check.main(verbose=ctx.obj.verbose, timeout=ctx.obj.timeout)
  File "/usr/lib/python3/dist-packages/nagiosplugin/check.py", line 121, in main
    runtime.execute(self, verbose, timeout)
  File "/usr/lib/python3/dist-packages/nagiosplugin/runtime.py", line 129, in execute
    with_timeout(self.timeout, self.run, check)
  File "/usr/lib/python3/dist-packages/nagiosplugin/platform/posix.py", line 17, in with_timeout
    func(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/nagiosplugin/runtime.py", line 118, in run
    check()
  File "/usr/lib/python3/dist-packages/nagiosplugin/check.py", line 106, in __call__
    self._evaluate_resource(resource)
  File "/usr/lib/python3/dist-packages/nagiosplugin/check.py", line 73, in _evaluate_resource
    metrics = resource.probe()
  File "/usr/lib/python3/dist-packages/check_patroni/node.py", line 251, in probe
    self.rest_api("liveness")
  File "/usr/lib/python3/dist-packages/check_patroni/types.py", line 74, in rest_api
    except requests.JSONDecodeError:
AttributeError: module 'requests' has no attribute 'JSONDecodeError'
dlax commented 1 year ago

@leeroyke, I tried this on my side with the debian package on a sid system and got no problem.

Though the error you get seems to be related to the python3-requests package being non-functional. Can you run this?

# python3 -c 'import requests; print(requests.JSONDecodeError)'
leeroyke commented 1 year ago

Actually the problem comes from the debian package python3-requests 2.25, available in Debian 11.

If i run this command with package python3-requests 2.25, the class JSONDecodeError return a error :

# python3 -c 'import requests; print(requests.JSONDecodeError)'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: module 'requests' has no attribute 'JSONDecodeError'

This issues has been reported in python here : https://github.com/python/typeshed/issues/7072 and this fix here : https://github.com/python/typeshed/pull/7171

In Debian 12 and package python3-requests 2.28.1 this issues has fixed.

Sorry for the inconvenience, I report this bug in Debian for the package python3-requests 2.25 here : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1052328

dlax commented 1 year ago

In requests 2.25, the top-level requests namespace does not re-export the JSONDecodeError name, see https://github.com/psf/requests/blob/v2.25.1/requests/__init__.py. So the error you get there is normal. I would assume this would work with python3 -c 'import requests.exceptions; print(requests.exceptions.JSONDecodeError)' (which is the current way it's done in check_patroni).

This issues has been reported in python here : python/typeshed#7072 and this fix here : python/typeshed#7171

These issues are about typing and should have no effect at runtime, so I think it's unrelated.

I'm also quite surprised you mention this old requests version as you earlier said you were packaging check_patroni for Debian/Sid?!

In any case, it does not seem we can do anything on our side, so the issue might be closed IMO.

leeroyke commented 1 year ago

Thanks for your feedback.

We have packaged check_patroni for Debian, but since the package is new, we can only deploy it on Debian Sid at this time. But I tested the package on a pre-production server in Debian 11, because for me the dependencies were resolved, without knowing that there was a bug in version 2.25 of python3-requests.

I close this issue.

dlax commented 1 year ago

59 should resolve this issue.