pyceo/ceod/api/app_factory.py

119 lines
3.7 KiB
Python

import importlib.resources
import os
import socket
from flask import Flask
from flask_kerberos import init_kerberos
from zope import component
from .error_handlers import register_error_handlers
from .krb5_cred_handlers import before_request, teardown_request
from ceo_common.interfaces import IConfig, IKerberosService, ILDAPService, IFileService, \
IMailmanService, IMailService, IUWLDAPService, IHTTPClient, IDatabaseService
from ceo_common.model import Config, HTTPClient, RemoteMailmanService
from ceod.model import KerberosService, LDAPService, FileService, \
MailmanService, MailService, UWLDAPService
from ceod.db import MySQLService, PostgreSQLService
def create_app(flask_config={}):
app = Flask(__name__)
app.config.from_mapping(flask_config)
if not app.config.get('TESTING'):
register_services(app)
cfg = component.getUtility(IConfig)
fqdn = socket.getfqdn()
os.environ['KRB5_KTNAME'] = '/etc/krb5.keytab'
init_kerberos(app, service='ceod', hostname=fqdn)
hostname = socket.gethostname()
# Only ceod_admin_host should serve the /api/members endpoints because
# it needs to run kadmin
if hostname == cfg.get('ceod_admin_host'):
from ceod.api import members
app.register_blueprint(members.bp, url_prefix='/api/members')
# Only offer mailman API if this host is running Mailman
if hostname == cfg.get('ceod_mailman_host'):
from ceod.api import mailman
app.register_blueprint(mailman.bp, url_prefix='/api/mailman')
from ceod.api import groups
app.register_blueprint(groups.bp, url_prefix='/api/groups')
from ceod.api import uwldap
app.register_blueprint(uwldap.bp, url_prefix='/api/uwldap')
register_error_handlers(app)
app.before_request(before_request)
app.teardown_request(teardown_request)
@app.route('/ping')
def ping():
"""Health check"""
return 'pong\n'
return app
def register_services(app):
# Config
if app.config.get('ENV') == 'development' and 'CEOD_CONFIG' not in os.environ:
with importlib.resources.path('tests', 'ceod_dev.ini') as p:
config_file = p.__fspath__()
else:
config_file = None
cfg = Config(config_file)
component.provideUtility(cfg, IConfig)
# KerberosService
if 'KRB5_KTNAME' not in os.environ:
os.environ['KRB5_KTNAME'] = '/etc/krb5.keytab'
hostname = socket.gethostname()
fqdn = socket.getfqdn()
# Only ceod_admin_host has the ceod/admin key in its keytab
if hostname == cfg.get('ceod_admin_host'):
principal = cfg.get('ldap_admin_principal')
else:
principal = f'ceod/{fqdn}'
krb_srv = KerberosService(principal)
component.provideUtility(krb_srv, IKerberosService)
# LDAPService
ldap_srv = LDAPService()
component.provideUtility(ldap_srv, ILDAPService)
# HTTPService
http_client = HTTPClient()
component.provideUtility(http_client, IHTTPClient)
# FileService
if hostname == cfg.get('ceod_fs_root_host'):
file_srv = FileService()
component.provideUtility(file_srv, IFileService)
# MailmanService
if hostname == cfg.get('ceod_mailman_host'):
mailman_srv = MailmanService()
else:
mailman_srv = RemoteMailmanService()
component.provideUtility(mailman_srv, IMailmanService)
# MailService
mail_srv = MailService()
component.provideUtility(mail_srv, IMailService)
# UWLDAPService
uwldap_srv = UWLDAPService()
component.provideUtility(uwldap_srv, IUWLDAPService)
# MySQLService
mysql_srv = MySQLService()
component.provideUtility(mysql_srv, IDatabaseService, 'mysql')
# PostgreSQLService
psql_srv = PostgreSQLService()
component.provideUtility(psql_srv, IDatabaseService, 'postgresql')