Update server config, SSL handling, and port mapping logic
Refactored `run_server` to accept explicit config and SSL paths. Added dynamic environment-based config loading and stricter SSL path checks for production. Updated `docker-compose.yml` to use environment variable for port mapping and adjusted `config_prod.json` to reflect correct port usage.
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"ssl_cert_path": "/app/backend/ssl/mx-aare-test.psi.ch.pem",
|
"ssl_cert_path": "/app/backend/ssl/mx-aare-test.psi.ch.pem",
|
||||||
"ssl_key_path": "/app/backend/ssl/mx-aare-test.psi.ch.key",
|
"ssl_key_path": "/app/backend/ssl/mx-aare-test.psi.ch.key",
|
||||||
"OPENAPI_URL": "https://backend:8000/openapi.json",
|
"PORT": 1492,
|
||||||
|
"OPENAPI_URL": "https://backend:1492/openapi.json",
|
||||||
"SCHEMA_PATH": "/app/src/openapi.json",
|
"SCHEMA_PATH": "/app/src/openapi.json",
|
||||||
"OUTPUT_DIRECTORY": "/app/openapi",
|
"OUTPUT_DIRECTORY": "/app/openapi",
|
||||||
"PORT": 8000,
|
|
||||||
"SSL_KEY_PATH": "/app/backend/ssl/mx-aare-test.psi.ch.key",
|
"SSL_KEY_PATH": "/app/backend/ssl/mx-aare-test.psi.ch.key",
|
||||||
"SSL_CERT_PATH": "/app/backend/ssl/mx-aare-test.psi.ch.pem"
|
"SSL_CERT_PATH": "/app/backend/ssl/mx-aare-test.psi.ch.pem"
|
||||||
}
|
}
|
@ -50,21 +50,26 @@ def get_project_metadata():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_server():
|
def run_server(config, cert_path, key_path):
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
|
environment = os.getenv(
|
||||||
|
"ENVIRONMENT", "dev"
|
||||||
|
) # needs to be set explicitly here if not globally available
|
||||||
|
|
||||||
print(f"[INFO] Starting server in {environment} environment...")
|
print(f"[INFO] Starting server in {environment} environment...")
|
||||||
print(f"[INFO] SSL Certificate Path: {cert_path}")
|
print(f"[INFO] SSL Certificate Path: {cert_path}")
|
||||||
print(f"[INFO] SSL Key Path: {key_path}")
|
print(f"[INFO] SSL Key Path: {key_path}")
|
||||||
port = config.get("PORT", os.getenv("PORT"))
|
port = config.get("PORT")
|
||||||
if not port:
|
if not port:
|
||||||
print("[ERROR] No port defined in config or environment variables. Aborting!")
|
print("[ERROR] No port defined in config or environment variables. Aborting!")
|
||||||
sys.exit(1) # Exit if no port is defined
|
sys.exit(1) # Exit if no port is defined
|
||||||
port = int(port)
|
port = int(port)
|
||||||
print(f"[INFO] Running on port {port}")
|
print(f"[INFO] Running on port {port}")
|
||||||
|
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
app,
|
app,
|
||||||
host="0.0.0.0" if environment in ["dev", "test"] else "0.0.0.0",
|
host="0.0.0.0",
|
||||||
port=port,
|
port=port,
|
||||||
log_level="debug",
|
log_level="debug",
|
||||||
ssl_keyfile=key_path,
|
ssl_keyfile=key_path,
|
||||||
@ -214,6 +219,9 @@ if __name__ == "__main__":
|
|||||||
# Load environment variables from .env file
|
# Load environment variables from .env file
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
|
environment = os.getenv("ENVIRONMENT", "dev")
|
||||||
|
config_file = Path(__file__).resolve().parent / f"config_{environment}.json"
|
||||||
|
|
||||||
# Check if `generate-openapi` option is passed
|
# Check if `generate-openapi` option is passed
|
||||||
if len(sys.argv) > 1 and sys.argv[1] == "generate-openapi":
|
if len(sys.argv) > 1 and sys.argv[1] == "generate-openapi":
|
||||||
from fastapi.openapi.utils import get_openapi
|
from fastapi.openapi.utils import get_openapi
|
||||||
@ -230,28 +238,42 @@ if __name__ == "__main__":
|
|||||||
print("openapi.json generated successfully.")
|
print("openapi.json generated successfully.")
|
||||||
sys.exit(0) # Exit after generating the file
|
sys.exit(0) # Exit after generating the file
|
||||||
|
|
||||||
# Default behavior: Run the server based on the environment
|
# Explicitly load the configuration file
|
||||||
environment = os.getenv("ENVIRONMENT", "dev")
|
with open(config_file, "r") as f:
|
||||||
port = int(os.getenv("PORT", 8000))
|
config = json.load(f)
|
||||||
|
|
||||||
|
# Explicitly obtain SSL paths from config
|
||||||
|
if environment in ["test", "dev"]:
|
||||||
|
cert_path = config.get("ssl_cert_path", "ssl/cert.pem")
|
||||||
|
key_path = config.get("ssl_key_path", "ssl/key.pem")
|
||||||
|
elif environment == "prod":
|
||||||
|
cert_path = config.get("SSL_CERT_PATH")
|
||||||
|
key_path = config.get("SSL_KEY_PATH")
|
||||||
|
if not cert_path or not key_path:
|
||||||
|
raise ValueError(
|
||||||
|
"SSL_CERT_PATH and SSL_KEY_PATH must be explicitly"
|
||||||
|
"set in config_prod.json for production."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unknown environment: {environment}")
|
||||||
|
|
||||||
is_ci = os.getenv("CI", "false").lower() == "true"
|
is_ci = os.getenv("CI", "false").lower() == "true"
|
||||||
|
|
||||||
if is_ci or environment == "test":
|
# Handle certificates for dev/test if not available
|
||||||
# Test or CI Mode: Run server process temporarily for test validation
|
|
||||||
ssl_dir = Path(cert_path).parent
|
ssl_dir = Path(cert_path).parent
|
||||||
ssl_dir.mkdir(parents=True, exist_ok=True)
|
ssl_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
if environment in ["dev", "test"] and (
|
||||||
# Generate self-signed certs if missing
|
not Path(cert_path).exists() or not Path(key_path).exists()
|
||||||
if not Path(cert_path).exists() or not Path(key_path).exists():
|
):
|
||||||
print(f"[INFO] Generating self-signed SSL certificates at {ssl_dir}")
|
print(f"[INFO] Generating SSL certificates at {ssl_dir}")
|
||||||
ssl_heidi.generate_self_signed_cert(cert_path, key_path)
|
ssl_heidi.generate_self_signed_cert(cert_path, key_path)
|
||||||
|
|
||||||
# Start the server as a subprocess, wait, then terminate
|
if is_ci or environment == "test":
|
||||||
server_process = Process(target=run_server)
|
server_process = Process(target=run_server, args=(config, cert_path, key_path))
|
||||||
server_process.start()
|
server_process.start()
|
||||||
sleep(5) # Wait for 5 seconds to verify the server is running
|
sleep(5)
|
||||||
server_process.terminate() # Terminate the server process (for CI)
|
server_process.terminate()
|
||||||
server_process.join() # Ensure proper cleanup
|
server_process.join()
|
||||||
print("CI: Server started and terminated successfully for test validation.")
|
print("CI/Test environment: Server started and terminated successfully.")
|
||||||
else:
|
else:
|
||||||
# Dev or Prod: Start the server as usual
|
run_server(config, cert_path, key_path)
|
||||||
run_server()
|
|
||||||
|
@ -7,7 +7,7 @@ services:
|
|||||||
dockerfile: backend/Dockerfile
|
dockerfile: backend/Dockerfile
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000" # Map container port 8000 to host
|
- "${PORT}:${PORT}" # Map container port 8000 to host
|
||||||
volumes:
|
volumes:
|
||||||
- ./backend:/app/backend # Map backend directory to /app/backend
|
- ./backend:/app/backend # Map backend directory to /app/backend
|
||||||
- ./app:/app/app # Map app directory to /app/app
|
- ./app:/app/app # Map app directory to /app/app
|
||||||
@ -28,6 +28,7 @@ services:
|
|||||||
DB_PASSWORD: ${DB_PASSWORD}
|
DB_PASSWORD: ${DB_PASSWORD}
|
||||||
DB_HOST: postgres
|
DB_HOST: postgres
|
||||||
DB_NAME: ${DB_NAME}
|
DB_NAME: ${DB_NAME}
|
||||||
|
PORT: ${PORT}
|
||||||
|
|
||||||
postgres: # ⬅️ New service (our PostgreSQL database)
|
postgres: # ⬅️ New service (our PostgreSQL database)
|
||||||
image: postgres:16
|
image: postgres:16
|
||||||
|
Reference in New Issue
Block a user