Renamed stuff
All checks were successful
continuous-integration/drone Build is passing

This commit is contained in:
2021-12-10 23:08:58 +01:00
parent 3b5621278f
commit 2f5a4929a5
15 changed files with 17 additions and 17 deletions

View File

@ -0,0 +1,79 @@
#!/usr/bin/env python3
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from flask import Flask
from werkzeug.middleware.proxy_fix import ProxyFix
# import stuff
from utils import register_all_error_handlers, register_health_checks, redis_client
# import views
from views import AssignmentView
from config import Config
# Tracing stuffs
import jaeger_client
import opentracing
from flask_opentracing import FlaskTracing
# Setup sentry
if Config.SENTRY_DSN:
sentry_sdk.init(
dsn=Config.SENTRY_DSN,
integrations=[FlaskIntegration()],
traces_sample_rate=0,
send_default_pii=True,
release=Config.RELEASE_ID,
environment=Config.RELEASEMODE
)
# create flask app
app = Flask(__name__)
app.config.from_object(Config)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1)
# init stuff
redis_client.init_app(app)
# register error handlers
register_all_error_handlers(app)
# Setup tracing
def initialize_tracer():
app.logger.info("Initializing jaeger...")
jaeger_cfg = jaeger_client.Config(config={}, service_name='birb-scheduler-teller', validate=True)
tracer = jaeger_cfg.initialize_tracer()
return tracer
tracing = FlaskTracing(initialize_tracer, True, app)
# register views
for view in [AssignmentView]:
view.register(app, trailing_slash=False)
register_health_checks(app)
# start debugging if needed
if __name__ == "__main__":
app.run(debug=True)
else:
import os
if "gunicorn" in os.environ.get("SERVER_SOFTWARE", ""):
import logging
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
jaeger_logger = logging.getLogger('jaeger_tracing')
jaeger_logger.handlers = gunicorn_logger.handlers
jaeger_logger.setLevel(gunicorn_logger.level)
app.logger.info("Gunicorn environment detected!")
else:
app.logger.info("Not gunicorn")

View File

@ -0,0 +1,26 @@
import os
def parse_default_while_not_defined():
envvar = os.environ.get("DEFAULT_WHILE_NOT_DEFINED")
if not envvar:
return None, None
envvar = envvar.split(';', 1)[2:]
return envvar
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY', os.urandom(12))
SENTRY_DSN = os.environ.get("SENTRY_DSN")
RELEASE_ID = os.environ.get("RELEASE_ID", "test")
RELEASEMODE = os.environ.get("RELEASEMODE", "dev")
REDIS_URL = os.environ.get("REDIS_URL", "redis://localhost:6379/0")
DEFAULT_WHILE_NOT_DEFINED = parse_default_while_not_defined()
DEVICE_TIMEOUT = int(os.environ.get("DEVICE_TIMEOUT", 120))

View File

@ -0,0 +1 @@
#!/usr/bin/env python3

View File

@ -0,0 +1 @@
import os

View File

@ -0,0 +1,5 @@
#!/usr/bin/env python3
from .require_decorators import json_required
from .error_handlers import register_all_error_handlers
from .healthchecks import register_health_checks
from .redis_client import redis_client

View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
from flask import jsonify
def get_standard_error_handler(code: int):
def error_handler(err):
return jsonify({"msg": err.description, "status": code}), code
return error_handler
def register_all_error_handlers(app):
"""
function to register all handlers
"""
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))

View File

@ -0,0 +1,13 @@
#!/usr/bin/env python3
from healthcheck import HealthCheck
from flask import Flask
def health_database_status():
return True, f'db is ok'
def register_health_checks(app: Flask):
health = HealthCheck()
health.add_check(health_database_status)
app.add_url_rule("/healthz", "healthcheck", view_func=lambda: health.run())

View File

@ -0,0 +1,3 @@
from flask_redis import FlaskRedis
redis_client = FlaskRedis()

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
from flask import request, abort
from functools import wraps
def json_required(f):
@wraps(f)
def call(*args, **kwargs):
if request.is_json:
return f(*args, **kwargs)
else:
abort(400, "JSON required")
return call

View File

@ -0,0 +1,2 @@
#!/usr/bin/env python3
from .assignment_view import AssignmentView

View File

@ -0,0 +1,71 @@
#!/usr/bin/env python3
from typing import Optional
from flask import jsonify, request, abort, current_app
from utils import json_required, redis_client
from flask_classful import FlaskView
import json
class AssignmentView(FlaskView):
@staticmethod
def _resolve_response(site: Optional[str]) -> dict:
site_url_map = redis_client.get("SITEURLMAP")
if site_url_map:
site_url_map = json.loads(site_url_map.decode('utf-8'))
if not site_url_map:
return {
"site": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][0],
"url": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][1],
"hard_default": True
}
if not site:
return {
"site": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][0],
"url": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][1],
"hard_default": True
}
if site not in site_url_map.keys():
# This should be an internal server error instead
return {
"site": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][0],
"url": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][1],
"hard_default": True
}
return {
"site": site,
"url": site_url_map[site],
"hard_default": False
}
@json_required
def post(self):
device_id = request.json['device_id']
schedule_store_key = f"SCHEDULED:{device_id}"
target_site = redis_client.get(schedule_store_key)
if target_site:
target_site = target_site.decode('utf-8')
if not target_site:
default_target = redis_client.get('DEFAULT:SCHEDULED')
if default_target:
target_site = default_target.decode('utf-8')
redis_client.set(schedule_store_key, default_target)
# Update (or set) TTL
redis_client.expire(
schedule_store_key,
current_app.config['DEVICE_TIMEOUT']
)
return jsonify(self._resolve_response(target_site))