entities_service/app.py

144 lines
4.2 KiB
Python

#!/usr/bin/python3
from abc import ABCMeta
import tornado.web
import os
import subprocess
from datetime import datetime
import isodate
import json
import util
from auth import AuthProvider
from gitmgr import GitManagerConfiguration, GitManager
startup_timestamp = datetime.now()
class AuthenticatedHandler(tornado.web.RequestHandler, metaclass=ABCMeta):
# noinspection PyAttributeOutsideInit
def initialize(self, auth_provider=None):
self.auth_provider = auth_provider
def prepare(self):
if self.auth_provider is None:
return
# check authentication
auth_hdr = "Authentication"
if auth_hdr not in self.request.headers:
raise tornado.web.HTTPError(401, reason="authentication not provided")
tk = self.request.headers[auth_hdr]
if not self.auth_provider.validate_token(tk):
raise tornado.web.HTTPError(403, reason="invalid authentication token provided")
class HealthHandler(tornado.web.RequestHandler, metaclass=ABCMeta):
# noinspection PyAttributeOutsideInit
def initialize(self, sources=None):
self.git_version = self._load_git_version()
self.sources = sources
@staticmethod
def _load_git_version():
v = None
# try file git-version.txt first
gitversion_file = "git-version.txt"
if os.path.exists(gitversion_file):
with open(gitversion_file) as f:
v = f.readline().strip()
# if not available, try git
if v is None:
try:
v = subprocess.check_output(["git", "describe", "--always", "--dirty"],
cwd=os.path.dirname(__file__)).strip().decode()
except subprocess.CalledProcessError as e:
print("Checking git version lead to non-null return code ", e.returncode)
return v
def get(self):
health = dict()
health['api-version'] = 'v0'
if self.git_version is not None:
health['git-version'] = self.git_version
health['timestamp'] = isodate.datetime_isoformat(datetime.now())
health['uptime'] = isodate.duration_isoformat(datetime.now() - startup_timestamp)
if self.sources:
for s in self.sources:
h = s()
if h is not None:
health = {**health, **h}
self.set_header("Content-Type", "application/json")
self.write(json.dumps(health, indent=4))
self.set_status(200)
class Oas3Handler(tornado.web.RequestHandler, metaclass=ABCMeta):
def get(self):
self.set_header("Content-Type", "text/plain")
# This is the proposed content type,
# but browsers like Firefox try to download instead of display the content
# self.set_header("Content-Type", "text/vnd.yml")
with open('OAS3.yml', 'r') as f:
oas3 = f.read()
self.write(oas3)
self.finish()
class SingleEntityHandler(AuthenticatedHandler, metaclass=ABCMeta):
# noinspection PyAttributeOutsideInit
def initialize(self, auth_provider=None):
super().initialize(auth_provider)
def post(self, identifier):
pass
def get(self, identifier):
pass
def make_app(_auth_provider=None, gitmgr=None):
version_path = r"/v[0-9]"
return tornado.web.Application([
(version_path + r"/health", HealthHandler,
{"sources": [lambda: {"git-head": gitmgr.head_sha}] if gitmgr else None}),
(version_path + r"/oas3", Oas3Handler),
(version_path + r"/entities", AllEntitiesHandler, {"auth_provider": _auth_provider}),
(version_path + r"/entity/{.*}", SingleEntityHandler, {"auth_provider": _auth_provider}),
])
def main():
port = util.load_env('PORT', 8080)
# Setup
auth_provider = AuthProvider.from_environment()
gitcfg = GitManagerConfiguration.from_environment()
gitmgr = GitManager(configuration=gitcfg)
gitmgr.setup()
gitmgr.printout()
util.run_tornado_server(make_app(auth_provider, gitmgr),
server_port=port)
# Teardown
gitmgr.teardown()
print("Server stopped")
if __name__ == "__main__":
main()