Externalize all configuration parameters Pt.I

This commit is contained in:
Daniel Schick 2025-12-05 18:08:15 +01:00
parent dc98b1d500
commit c1e3e8939a
4 changed files with 95 additions and 27 deletions

View File

@ -1,6 +1,7 @@
from flask import Flask from flask import Flask
import os import os
import sys
import logging import logging
from . import local_db from . import local_db
@ -36,7 +37,6 @@ from BreCal.stubs.df_times import get_df_times
from BreCal.services.schedule_routines import setup_schedule, run_schedule_permanently_in_background from BreCal.services.schedule_routines import setup_schedule, run_schedule_permanently_in_background
def create_app(test_config=None, instance_path=None): def create_app(test_config=None, instance_path=None):
app = Flask(__name__, instance_relative_config=True) app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping( app.config.from_mapping(
SECRET_KEY='dev' SECRET_KEY='dev'
@ -48,6 +48,8 @@ def create_app(test_config=None, instance_path=None):
if instance_path is not None: if instance_path is not None:
app.instance_path = instance_path app.instance_path = instance_path
elif app.config.get("INSTANCE_PATH"):
app.instance_path = app.config["INSTANCE_PATH"]
try: try:
import os import os
@ -69,13 +71,23 @@ def create_app(test_config=None, instance_path=None):
app.register_blueprint(history.bp) app.register_blueprint(history.bp)
app.register_blueprint(ports.bp) app.register_blueprint(ports.bp)
logging.basicConfig(filename='brecaltest.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s') log_level = getattr(logging, app.config.get("LOG_LEVEL", "DEBUG"))
local_db.initPool(os.path.dirname(app.instance_path)) log_kwargs = {"format": "%(asctime)s | %(name)s | %(levelname)s | %(message)s"}
if app.config.get("LOG_TO_STDERR"):
log_kwargs["stream"] = sys.stderr
else:
log_kwargs["filename"] = app.config.get("LOG_FILE", "brecaltest.log")
logging.basicConfig(level=log_level, **log_kwargs)
if app.config.get("SECRET_KEY"):
os.environ["SECRET_KEY"] = app.config["SECRET_KEY"]
local_db.initPool(os.path.dirname(app.instance_path), config=app.config)
logging.info('App started') logging.info('App started')
# Setup Routine jobs (e.g., reevaluation of shipcalls) # Setup Routine jobs (e.g., reevaluation of shipcalls)
setup_schedule(update_shipcalls_interval_in_minutes=60) setup_schedule(update_shipcalls_interval_in_minutes=app.config.get("SCHEDULE_UPDATE_SHIPCALLS_MINUTES", 60))
run_schedule_permanently_in_background(latency=30) run_schedule_permanently_in_background(latency=app.config.get("SCHEDULE_BACKGROUND_LATENCY_SECONDS", 30))
logging.info('Routine Jobs are defined.') logging.info('Routine Jobs are defined.')
return app return app

View File

@ -8,6 +8,7 @@ import sys
from BreCal.schemas import defs from BreCal.schemas import defs
config_path = None config_path = None
secure_dir = None
_connection_pool = None _connection_pool = None
@ -23,17 +24,26 @@ def _build_pool_config(connection_data, pool_name, pool_size):
return pool_config return pool_config
def initPool(instancePath, connection_filename="connection_data_prod.json", def initPool(instancePath, config=None, connection_filename="connection_data_prod.json",
pool_name="brecal_pool", pool_size=10): credentials_file="email_credentials_test.json", pool_name="brecal_pool", pool_size=10,
secure_directory=None):
""" """
Initialize the MySQL connection pool and load email credentials. Initialize the MySQL connection pool and load email credentials.
""" """
global config_path, _connection_pool global config_path, secure_dir, _connection_pool
try: try:
if config_path is None: if config:
config_path = os.path.join(instancePath, f'../../../secure/{connection_filename}') connection_filename = config.get("DB_CONNECTION_FILE", connection_filename)
credentials_file = config.get("EMAIL_CREDENTIALS_FILE", credentials_file)
pool_name = config.get("DB_POOL_NAME", pool_name)
pool_size = config.get("DB_POOL_SIZE", pool_size)
secure_directory = config.get("SECURE_DIR", secure_directory)
# config_path = 'C:\\temp\\connection_data_test.json' if secure_dir is None:
secure_dir = secure_directory if secure_directory else os.path.join(instancePath, '../../../secure')
if config_path is None:
config_path = os.path.join(secure_dir, connection_filename)
print(config_path) print(config_path)
if not os.path.exists(config_path): if not os.path.exists(config_path):
@ -54,10 +64,7 @@ def initPool(instancePath, connection_filename="connection_data_prod.json",
finally: finally:
conn_from_pool.close() conn_from_pool.close()
credentials_file = "email_credentials_test.json" credentials_path = os.path.join(secure_dir, credentials_file)
credentials_path = os.path.join(instancePath, f'../../../secure/{credentials_file}')
# credentials_path = "E:/temp/email_credentials_devel.json"
if not os.path.exists(credentials_path): if not os.path.exists(credentials_path):
print('cannot find ' + os.path.abspath(credentials_path)) print('cannot find ' + os.path.abspath(credentials_path))

View File

@ -0,0 +1,40 @@
"""
Sample configuration for the Flask instance.
Copy this file to `src/server/instance/config.py` (the instance folder is git-ignored)
and adjust the values for each deployment target.
"""
# Flask
SECRET_KEY = "change-me"
# Python path adjustments used by the WSGI entrypoint (flaskapp.wsgi)
APP_ROOT = "/var/www/brecal/src/server"
SITE_PACKAGES = "/var/www/venv/lib/python3.12/site-packages/"
# Paths to environment-specific secrets and instance data
SECURE_DIR = "/var/www/secure" # directory that holds connection/email JSON files
INSTANCE_PATH = "/var/www/brecal/src/server/instance"
# Logging
LOG_FILE = "brecal.log"
LOG_LEVEL = "INFO" # e.g. DEBUG, INFO, WARNING
LOG_TO_STDERR = False
# Database pool setup
DB_CONNECTION_FILE = "connection_data_prod.json"
DB_POOL_NAME = "brecal_pool"
DB_POOL_SIZE = 10
# Email + notifications
EMAIL_CREDENTIALS_FILE = "email_credentials_prod.json"
EMAIL_URL_TEMPLATE = "https://brecal.example.com/shipcalls/" # base URL for links in emails
SMTP_DEBUG_LEVEL = 0 # 0 = quiet, 1 = verbose
# Scheduler cadence
SCHEDULE_UPDATE_SHIPCALLS_MINUTES = 60
SCHEDULE_BACKGROUND_LATENCY_SECONDS = 30
# Notification cleanup / escalation windows
NOTIFICATION_COOLDOWN_MINS = 10
NOTIFICATION_MAX_AGE_DAYS = 3

View File

@ -1,20 +1,29 @@
import os
import sys
import logging import logging
import os
import runpy
import sys
from pathlib import Path
sys.path.insert(0, '/var/www/brecal_test/src/server') BASE_DIR = Path(__file__).resolve().parent
sys.path.insert(0, '/var/www/venv/lib/python3.12/site-packages/') INSTANCE_DIR = BASE_DIR / "instance"
CONFIG_PATH = INSTANCE_DIR / "config.py"
import schedule config = {}
if CONFIG_PATH.exists():
config = runpy.run_path(str(CONFIG_PATH))
# set the key app_root = config.get("APP_ROOT", str(BASE_DIR))
os.environ['SECRET_KEY'] = 'zdiTz8P3jXOc7jztIQAoelK4zztyuCpJ' site_packages = config.get("SITE_PACKAGES")
# Set up logging sys.path.insert(0, app_root)
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) if site_packages:
sys.path.insert(0, site_packages)
# Set up Scheduled Jobs if config.get("SECRET_KEY"):
os.environ["SECRET_KEY"] = config["SECRET_KEY"]
log_kwargs = {"level": getattr(logging, config.get("LOG_LEVEL", "DEBUG")), "stream": sys.stderr}
logging.basicConfig(**log_kwargs)
# Import and run the Flask app
from BreCal import create_app from BreCal import create_app
application = create_app() application = create_app(instance_path=config.get("INSTANCE_PATH"))