From f41696c31084f363a4c1c42c7b078e6a3fe8b3cd Mon Sep 17 00:00:00 2001 From: root Date: Mon, 18 Apr 2022 09:01:22 +0000 Subject: [PATCH 1/5] WIP - Added health check --- powerdnsadmin/lib/errors.py | 8 ++++++++ powerdnsadmin/routes/api.py | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/powerdnsadmin/lib/errors.py b/powerdnsadmin/lib/errors.py index 687f554..b820017 100644 --- a/powerdnsadmin/lib/errors.py +++ b/powerdnsadmin/lib/errors.py @@ -171,3 +171,11 @@ class UserDeleteFail(StructuredException): StructuredException.__init__(self) self.message = message self.name = name + +class HealthCheckFail(StructuredException): + status_code = 500 + + def __init__(self,name=None, message="Health check failed"): + StructuredException.__init__(self) + self.message = message + self.name = name \ No newline at end of file diff --git a/powerdnsadmin/routes/api.py b/powerdnsadmin/routes/api.py index 4fce368..580e1a1 100644 --- a/powerdnsadmin/routes/api.py +++ b/powerdnsadmin/routes/api.py @@ -23,7 +23,7 @@ from ..lib.errors import ( AccountCreateFail, AccountUpdateFail, AccountDeleteFail, AccountCreateDuplicate, AccountNotExists, UserCreateFail, UserCreateDuplicate, UserUpdateFail, UserDeleteFail, - UserUpdateFailEmail, + UserUpdateFailEmail, HealthCheckFail ) from ..decorators import ( api_basic_auth, api_can_create_domain, is_json, apikey_auth, @@ -1182,3 +1182,36 @@ def sync_domains(): domain = Domain() domain.update() return 'Finished synchronization in background', 200 + +@api_bp.route('/health', methods=['GET']) +def health(): + domain = Domain() + domain_to_query = domain.query.first() + + if not domain_to_query: + current_app.logger.error("No domain found to query a health check") + raise (HealthCheckFail) + + pdns_api_url = Setting().get('pdns_api_url') + pdns_api_key = Setting().get('pdns_api_key') + pdns_version = Setting().get('pdns_version') + api_uri_with_prefix = utils.pdns_api_extended_uri(pdns_version) + api_uri = '/servers/localhost/zones/{}'.format(domain_to_query.name) + headers = {} + headers['X-API-Key'] = pdns_api_key + + try: + resp = utils.fetch_remote(urljoin(pdns_api_url, api_uri_with_prefix + api_uri), + method='GET', + headers=headers, + accept='application/json; q=1', + verify=Setting().get('verify_ssl_connections')) + + except Exception as e: + current_app.logger.error("Health Check - Failed to query authoritative server for domain {}".format(domain_to_query.name)) + return make_response("bad", 503) + + if resp.status_code == 200: + return make_response("good", 200) + else: + return make_response("bad", 503) \ No newline at end of file From 4958423cc74a929f052f4da6dea9f684f33b5850 Mon Sep 17 00:00:00 2001 From: RGanor <44501230+RGanor@users.noreply.github.com> Date: Mon, 18 Apr 2022 22:11:31 +0300 Subject: [PATCH 2/5] Update api.py --- powerdnsadmin/routes/api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/powerdnsadmin/routes/api.py b/powerdnsadmin/routes/api.py index 580e1a1..7ce363d 100644 --- a/powerdnsadmin/routes/api.py +++ b/powerdnsadmin/routes/api.py @@ -1214,4 +1214,5 @@ def health(): if resp.status_code == 200: return make_response("good", 200) else: - return make_response("bad", 503) \ No newline at end of file + return make_response("bad", 503) + From b3271e84d6153b0157f887e5a5cab7e86eaba468 Mon Sep 17 00:00:00 2001 From: Cloud User Date: Sun, 15 May 2022 12:19:04 +0000 Subject: [PATCH 3/5] Using domain model and added authentication --- powerdnsadmin/lib/errors.py | 8 -------- powerdnsadmin/routes/api.py | 28 ++++++---------------------- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/powerdnsadmin/lib/errors.py b/powerdnsadmin/lib/errors.py index b820017..687f554 100644 --- a/powerdnsadmin/lib/errors.py +++ b/powerdnsadmin/lib/errors.py @@ -171,11 +171,3 @@ class UserDeleteFail(StructuredException): StructuredException.__init__(self) self.message = message self.name = name - -class HealthCheckFail(StructuredException): - status_code = 500 - - def __init__(self,name=None, message="Health check failed"): - StructuredException.__init__(self) - self.message = message - self.name = name \ No newline at end of file diff --git a/powerdnsadmin/routes/api.py b/powerdnsadmin/routes/api.py index 7ce363d..cf74986 100644 --- a/powerdnsadmin/routes/api.py +++ b/powerdnsadmin/routes/api.py @@ -23,7 +23,7 @@ from ..lib.errors import ( AccountCreateFail, AccountUpdateFail, AccountDeleteFail, AccountCreateDuplicate, AccountNotExists, UserCreateFail, UserCreateDuplicate, UserUpdateFail, UserDeleteFail, - UserUpdateFailEmail, HealthCheckFail + UserUpdateFailEmail ) from ..decorators import ( api_basic_auth, api_can_create_domain, is_json, apikey_auth, @@ -1184,35 +1184,19 @@ def sync_domains(): return 'Finished synchronization in background', 200 @api_bp.route('/health', methods=['GET']) +@apikey_auth def health(): domain = Domain() domain_to_query = domain.query.first() if not domain_to_query: current_app.logger.error("No domain found to query a health check") - raise (HealthCheckFail) - - pdns_api_url = Setting().get('pdns_api_url') - pdns_api_key = Setting().get('pdns_api_key') - pdns_version = Setting().get('pdns_version') - api_uri_with_prefix = utils.pdns_api_extended_uri(pdns_version) - api_uri = '/servers/localhost/zones/{}'.format(domain_to_query.name) - headers = {} - headers['X-API-Key'] = pdns_api_key + return make_response("Down", 503) try: - resp = utils.fetch_remote(urljoin(pdns_api_url, api_uri_with_prefix + api_uri), - method='GET', - headers=headers, - accept='application/json; q=1', - verify=Setting().get('verify_ssl_connections')) - + resp = domain.get_domain_info(domain_to_query.name) except Exception as e: current_app.logger.error("Health Check - Failed to query authoritative server for domain {}".format(domain_to_query.name)) - return make_response("bad", 503) + return make_response("Down", 503) - if resp.status_code == 200: - return make_response("good", 200) - else: - return make_response("bad", 503) - + return make_response("Up", 200) From 3d2ad1abc0f60297156a517c7731ed92942c6d60 Mon Sep 17 00:00:00 2001 From: RGanor Date: Sun, 15 May 2022 13:57:13 +0000 Subject: [PATCH 4/5] LGTM fix - unused variable --- powerdnsadmin/routes/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerdnsadmin/routes/api.py b/powerdnsadmin/routes/api.py index cf74986..6a6d74e 100644 --- a/powerdnsadmin/routes/api.py +++ b/powerdnsadmin/routes/api.py @@ -1194,7 +1194,7 @@ def health(): return make_response("Down", 503) try: - resp = domain.get_domain_info(domain_to_query.name) + domain.get_domain_info(domain_to_query.name) except Exception as e: current_app.logger.error("Health Check - Failed to query authoritative server for domain {}".format(domain_to_query.name)) return make_response("Down", 503) From 1bee83332659d1d2e5c96a4edf41c1435a625c7e Mon Sep 17 00:00:00 2001 From: RGanor Date: Mon, 23 May 2022 16:46:11 +0000 Subject: [PATCH 5/5] Updated the unknown state --- powerdnsadmin/routes/api.py | 2 +- powerdnsadmin/swagger-spec.yaml | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/powerdnsadmin/routes/api.py b/powerdnsadmin/routes/api.py index 6a6d74e..d26deb8 100644 --- a/powerdnsadmin/routes/api.py +++ b/powerdnsadmin/routes/api.py @@ -1191,7 +1191,7 @@ def health(): if not domain_to_query: current_app.logger.error("No domain found to query a health check") - return make_response("Down", 503) + return make_response("Unknown", 503) try: domain.get_domain_info(domain_to_query.name) diff --git a/powerdnsadmin/swagger-spec.yaml b/powerdnsadmin/swagger-spec.yaml index dbf484e..75b1d9f 100644 --- a/powerdnsadmin/swagger-spec.yaml +++ b/powerdnsadmin/swagger-spec.yaml @@ -782,6 +782,32 @@ paths: '422': description: 'Returned when something is wrong with the content of the request. Contains an error message' + '/servers/{server_id}/health': + get: + security: + - APIKeyHeader: [] + summary: Perfoms health check + operationId: health_check + tags: + - Monitoring + parameters: + - name: server_id + in: path + required: true + description: The id of the server to retrieve + type: string + responses: + '200': + description: Healthcheck succeeded + schema: + type: string + example: "up" + '503': + description: Healthcheck failed + schema: + type: string + example: Down/Unknown + '/pdnsadmin/zones': get: security: