complete easy endpoints

This commit is contained in:
Torma Kristóf 2021-11-11 18:52:56 +01:00
parent 58c8708467
commit 8bff435ef3
Signed by: tormakris
GPG Key ID: DC83C4F2C41B1047
6 changed files with 172 additions and 5 deletions

View File

@ -4,4 +4,5 @@ Flask
Flask-RESTful
marshmallow
flask-marshmallow
flask-redis
flask-redis
py-healthcheck

View File

@ -2,12 +2,16 @@
from flask import Flask
from flask_restful import Api
import sentry_sdk
from healthcheck import HealthCheck
from sentry_sdk.integrations.flask import FlaskIntegration
from redis_client import redis_client
from config import Config
from marshm import ma
from resources import SampleResource
from errorhandlers import register_all_error_handlers
from healthchecks import redis_available
from resources import ServiceDiscoveryResource, ServiceLocationResource, ServiceDatabaseResource, \
ServiceDatabaseItemResource
"""
Main Flask RESTful API
@ -33,12 +37,18 @@ app.config.from_object(Config)
api = Api(app)
ma.init_app(app)
health = HealthCheck()
redis_client.init_app(app)
api.add_resource(ServiceDiscoveryResource, "/service/directory")
api.add_resource(ServiceLocationResource, "/service/location/<serviceid>")
api.add_resource(ServiceDatabaseResource, "/service")
api.add_resource(ServiceDatabaseItemResource, "/service/<serviceid>")
api.add_resource(SampleResource, "/input")
health.add_check(redis_available)
app.add_url_rule("/healthz", "healthcheck", view_func=lambda: health.run())
register_all_error_handlers(app)
if __name__ != '__main__':
import logging

View File

@ -19,4 +19,4 @@ class Config:
RELEASE_ID = os.environ.get("RELEASE_ID", "test")
RELEASEMODE = os.environ.get("RELEASEMODE", "dev")
REDIS_URL = os.environ['CACHE_REDIS_URL']
REDIS_URL = os.environ['REDIS_URL']

27
src/errorhandlers.py Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env python3
"""
Flask error handler functions
"""
__author__ = '@tormakris'
__copyright__ = "Copyright 2021, KMLabz Team"
__module_name__ = "errorhandlers"
__version__text__ = "1"
def get_standard_error_handler(code: int):
def error_handler(err):
return {"msg": str(err)}, code
return error_handler
# function to register all handlers
def register_all_error_handlers(app):
error_codes_to_override = [404, 403, 401, 405, 400, 409, 422]
for code in error_codes_to_override:
app.register_error_handler(code, get_standard_error_handler(code))

17
src/healthchecks.py Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env python3
from redis_client import redis_client
"""
Healthchek functions
"""
__author__ = "@tormakris"
__copyright__ = "Copyright 2021, KMLabz Team"
__module_name__ = "healthchecks"
__version__text__ = "1"
def redis_available():
redisstatus = redis_client.info()
return True, redisstatus

View File

@ -0,0 +1,112 @@
"""
Endpoinds to serve location API
"""
__author__ = '@tormakris'
__copyright__ = "Copyright 2021, KMLabz Team"
__module_name__ = "resources"
__version__text__ = "1"
import json
import random
from flask import request, current_app, abort
from flask_restful import Resource
from redis_client import redis_client
from schemas import ServiceLocatorSchema, ServiceDirectorySchema
class ServiceDiscoveryResource(Resource):
"""
Service Discovery endpoint
"""
servicedirectoryschema = ServiceDirectorySchema(many=True)
def get(self):
try:
servicelist = self.servicedirectoryschema.load(json.load(redis_client.get('servicelist').decode('UTF-8')))
except Exception as e:
current_app.logger.info(e)
abort(404, "not found")
return self.servicedirectoryschema.dump(servicelist), 200
class ServiceLocationResource(Resource):
"""
Service location endpoint
"""
servicelocatorschema = ServiceLocatorSchema(many=False)
def get(self, serviceid: str):
try:
serviceobject: dict = self.servicelocatorschema.load(json.load(redis_client.get(serviceid).decode('UTF-8')))
servicelocation: str = random.choice(serviceobject['servicearray'])['location']
except Exception as e:
current_app.logger.info(e)
abort(404, "not found")
return {"location": servicelocation}, 200
class ServiceDatabaseResource(Resource):
"""
Service database endpoint
"""
servicelocatorschema = ServiceLocatorSchema(many=False)
servicedirectoryschema = ServiceDirectorySchema(many=True)
def post(self):
try:
body = request.get_json()
except Exception as e:
current_app.logger.info(e)
abort(400, "JSON parse error")
try:
servicelocation = self.servicelocatorschema.load(body)
except Exception as e:
current_app.logger.info(e)
abort(417, "invalid JSON schema")
try:
redis_client.set(servicelocation['id'], self.servicelocatorschema.dump(servicelocation).encode('UTF-8'))
servicelist = self.servicedirectoryschema.load(json.load(redis_client.get('servicelist').decode('UTF-8')))
servicelist.append({"name": servicelocation['name'], "id": servicelocation['id']})
redis_client.set('servicelist', self.servicedirectoryschema.dump(servicelist).encode('UTF-8'))
except Exception as e:
current_app.logger.info(e)
abort(404, "not found")
return 200
class ServiceDatabaseItemResource(Resource):
"""
Service database endpoint interacting with individual items
"""
servicelocatorschema = ServiceLocatorSchema(many=False)
servicedirectoryschema = ServiceDirectorySchema(many=True)
def put(self, serviceid: str):
try:
body = request.get_json()
except Exception as e:
current_app.logger.info(e)
abort(400, "JSON parse error")
try:
servicelocation = self.servicelocatorschema.load(body)
except Exception as e:
current_app.logger.info(e)
abort(417, "invalid JSON schema")
try:
redis_client.get(serviceid)
redis_client.set(serviceid, self.servicelocatorschema.dump(servicelocation).encode('UTF-8'))
except Exception as e:
current_app.logger.info(e)
abort(404, "not found")
return 200
def get(self, serviceid: str):
try:
servicelocation = self.servicelocatorschema.load(json.load(redis_client.get(serviceid).decode('UTF-8')))
except Exception as e:
current_app.logger.info(e)
abort(404, "not found")
return servicelocation, 200