128 lines
4 KiB
Python
128 lines
4 KiB
Python
"""Flask extension for MinIO storage client initialization"""
|
|
|
|
import logging
|
|
|
|
from flask import Flask
|
|
from minio import Minio
|
|
from minio.error import S3Error
|
|
|
|
|
|
class StorageExtension:
|
|
"""Flask extension for managing MinIO storage client"""
|
|
|
|
def __init__(self, app: Flask = None):
|
|
"""
|
|
Initialize StorageExtension
|
|
|
|
Args:
|
|
app: Flask application instance (optional)
|
|
"""
|
|
self.app = app
|
|
self.client = None
|
|
self.logger = logging.getLogger(__name__)
|
|
if app is not None:
|
|
self.init_app(app)
|
|
|
|
def init_app(self, app: Flask) -> None:
|
|
"""
|
|
Initialize the extension with Flask app
|
|
|
|
Args:
|
|
app: Flask application instance
|
|
"""
|
|
# Store extension on app
|
|
app.extensions = getattr(app, "extensions", {})
|
|
app.extensions["storage"] = self
|
|
|
|
# Store app reference for later use
|
|
self.app = app
|
|
|
|
# Initialize and validate MinIO client immediately at app startup
|
|
self._initialize_and_validate(app)
|
|
|
|
def _initialize_and_validate(self, app: Flask) -> None:
|
|
"""
|
|
Initialize MinIO client and validate connection
|
|
|
|
Args:
|
|
app: Flask application instance
|
|
"""
|
|
try:
|
|
# Create MinIO client
|
|
self.client = Minio(
|
|
app.config["MINIO_ENDPOINT"],
|
|
access_key=app.config["MINIO_ACCESS_KEY"],
|
|
secret_key=app.config["MINIO_SECRET_KEY"],
|
|
secure=app.config["MINIO_USE_SSL"],
|
|
)
|
|
|
|
# Validate connection by listing buckets
|
|
self.client.list_buckets()
|
|
app.logger.info("MinIO client initialized and validated successfully")
|
|
|
|
# Ensure all required buckets exist
|
|
self._ensure_all_buckets_exist(app)
|
|
|
|
except S3Error as e:
|
|
app.logger.error(f"Failed to initialize MinIO client: {e}")
|
|
raise RuntimeError(
|
|
f"Failed to connect to MinIO at {app.config['MINIO_ENDPOINT']}. "
|
|
"Please check your MINIO_ENDPOINT, MINIO_ACCESS_KEY, "
|
|
"and MINIO_SECRET_KEY configuration."
|
|
) from e
|
|
except KeyError as e:
|
|
app.logger.error(f"Missing MinIO configuration: {e}")
|
|
raise RuntimeError(
|
|
f"Missing required MinIO configuration: {e}. "
|
|
"Please ensure MINIO_ENDPOINT, MINIO_ACCESS_KEY, "
|
|
"MINIO_SECRET_KEY are set."
|
|
) from e
|
|
|
|
def _ensure_all_buckets_exist(self, app: Flask) -> None:
|
|
"""
|
|
Ensure all required buckets exist
|
|
Creates buckets if they don't exist
|
|
|
|
Args:
|
|
app: Flask application instance
|
|
"""
|
|
buckets = [
|
|
app.config["MINIO_IMAGES_BUCKET"],
|
|
app.config["MINIO_DOCUMENTS_BUCKET"],
|
|
app.config["MINIO_THUMBNAILS_BUCKET"],
|
|
]
|
|
|
|
for bucket_name in buckets:
|
|
try:
|
|
if not self.client.bucket_exists(bucket_name):
|
|
self.client.make_bucket(bucket_name)
|
|
app.logger.info(f"Created MinIO bucket: {bucket_name}")
|
|
else:
|
|
app.logger.debug(f"MinIO bucket already exists: {bucket_name}")
|
|
except S3Error as e:
|
|
app.logger.error(f"Failed to ensure bucket {bucket_name}: {e}")
|
|
raise RuntimeError(
|
|
f"Failed to create MinIO bucket '{bucket_name}': {e}"
|
|
) from e
|
|
|
|
def get_client(self) -> Minio:
|
|
"""
|
|
Get the MinIO client instance
|
|
|
|
Returns:
|
|
Minio: Initialized MinIO client
|
|
|
|
Raises:
|
|
RuntimeError: If client has not been initialized
|
|
"""
|
|
if self.client is None:
|
|
raise RuntimeError(
|
|
"MinIO client has not been initialized. "
|
|
"Ensure the Flask app context is active "
|
|
"and before_first_request has run."
|
|
)
|
|
return self.client
|
|
|
|
|
|
# Create a singleton instance
|
|
storage = StorageExtension()
|