117 lines
3.4 KiB
Python
117 lines
3.4 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
|
|
|
|
|
|
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):
|
|
self.git_version = self._load_git_version()
|
|
|
|
@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)
|
|
|
|
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()
|
|
|
|
|
|
def make_app(auth_provider=None):
|
|
version_path = r"/v[0-9]"
|
|
return tornado.web.Application([
|
|
(version_path + r"/health", HealthHandler),
|
|
(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()
|
|
|
|
util.run_tornado_server(make_app(auth_provider),
|
|
server_port=port)
|
|
|
|
# Teardown
|
|
|
|
print("Server stopped")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|