Phase 2 build initial
This commit is contained in:
288
hcfs-python/hcfs/api/config.py
Normal file
288
hcfs-python/hcfs/api/config.py
Normal file
@@ -0,0 +1,288 @@
|
||||
"""
|
||||
Configuration management for HCFS API.
|
||||
|
||||
Handles environment-based configuration with validation and defaults.
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import List, Optional, Dict, Any
|
||||
from pydantic import BaseSettings, Field, validator
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class DatabaseConfig(BaseSettings):
|
||||
"""Database configuration settings."""
|
||||
|
||||
# SQLite settings
|
||||
db_path: str = Field(default="hcfs_production.db", description="Path to SQLite database")
|
||||
vector_db_path: str = Field(default="hcfs_vectors_production.db", description="Path to vector database")
|
||||
|
||||
# Connection settings
|
||||
pool_size: int = Field(default=10, description="Database connection pool size")
|
||||
max_overflow: int = Field(default=20, description="Maximum connection overflow")
|
||||
pool_timeout: int = Field(default=30, description="Connection pool timeout in seconds")
|
||||
|
||||
# Performance settings
|
||||
cache_size: int = Field(default=1000, description="Database cache size")
|
||||
enable_wal_mode: bool = Field(default=True, description="Enable SQLite WAL mode")
|
||||
synchronous_mode: str = Field(default="NORMAL", description="SQLite synchronous mode")
|
||||
|
||||
class Config:
|
||||
env_prefix = "HCFS_DB_"
|
||||
|
||||
|
||||
class EmbeddingConfig(BaseSettings):
|
||||
"""Embedding system configuration."""
|
||||
|
||||
# Model settings
|
||||
model_name: str = Field(default="mini", description="Embedding model to use")
|
||||
cache_size: int = Field(default=2000, description="Embedding cache size")
|
||||
batch_size: int = Field(default=32, description="Batch processing size")
|
||||
|
||||
# Performance settings
|
||||
max_workers: int = Field(default=4, description="Maximum worker threads")
|
||||
timeout_seconds: int = Field(default=300, description="Operation timeout")
|
||||
|
||||
# Vector database settings
|
||||
vector_dimension: int = Field(default=384, description="Vector dimension")
|
||||
similarity_threshold: float = Field(default=0.0, description="Default similarity threshold")
|
||||
|
||||
class Config:
|
||||
env_prefix = "HCFS_EMBEDDING_"
|
||||
|
||||
|
||||
class APIConfig(BaseSettings):
|
||||
"""API server configuration."""
|
||||
|
||||
# Server settings
|
||||
host: str = Field(default="0.0.0.0", description="Server host")
|
||||
port: int = Field(default=8000, description="Server port")
|
||||
workers: int = Field(default=1, description="Number of worker processes")
|
||||
|
||||
# Security settings
|
||||
secret_key: str = Field(default="dev-secret-key-change-in-production", description="JWT secret key")
|
||||
algorithm: str = Field(default="HS256", description="JWT algorithm")
|
||||
token_expire_minutes: int = Field(default=30, description="JWT token expiration time")
|
||||
|
||||
# CORS settings
|
||||
cors_origins: List[str] = Field(
|
||||
default=["http://localhost:3000", "http://localhost:8080"],
|
||||
description="Allowed CORS origins"
|
||||
)
|
||||
cors_credentials: bool = Field(default=True, description="Allow credentials in CORS")
|
||||
|
||||
# Rate limiting
|
||||
rate_limit_requests: int = Field(default=100, description="Requests per minute")
|
||||
rate_limit_burst: int = Field(default=20, description="Burst requests allowed")
|
||||
|
||||
# Feature flags
|
||||
enable_auth: bool = Field(default=True, description="Enable authentication")
|
||||
enable_websocket: bool = Field(default=True, description="Enable WebSocket support")
|
||||
enable_metrics: bool = Field(default=True, description="Enable Prometheus metrics")
|
||||
enable_docs: bool = Field(default=True, description="Enable API documentation")
|
||||
|
||||
class Config:
|
||||
env_prefix = "HCFS_API_"
|
||||
|
||||
|
||||
class MonitoringConfig(BaseSettings):
|
||||
"""Monitoring and observability configuration."""
|
||||
|
||||
# Logging settings
|
||||
log_level: str = Field(default="INFO", description="Logging level")
|
||||
log_format: str = Field(default="json", description="Log format (json/text)")
|
||||
log_file: Optional[str] = Field(default=None, description="Log file path")
|
||||
|
||||
# Metrics settings
|
||||
metrics_enabled: bool = Field(default=True, description="Enable metrics collection")
|
||||
metrics_port: int = Field(default=9090, description="Metrics server port")
|
||||
|
||||
# Health check settings
|
||||
health_check_interval: int = Field(default=30, description="Health check interval in seconds")
|
||||
health_check_timeout: int = Field(default=5, description="Health check timeout")
|
||||
|
||||
# Tracing settings
|
||||
tracing_enabled: bool = Field(default=False, description="Enable distributed tracing")
|
||||
tracing_sample_rate: float = Field(default=0.1, description="Tracing sample rate")
|
||||
jaeger_endpoint: Optional[str] = Field(default=None, description="Jaeger endpoint")
|
||||
|
||||
class Config:
|
||||
env_prefix = "HCFS_MONITORING_"
|
||||
|
||||
|
||||
class RedisConfig(BaseSettings):
|
||||
"""Redis configuration for caching and rate limiting."""
|
||||
|
||||
# Connection settings
|
||||
host: str = Field(default="localhost", description="Redis host")
|
||||
port: int = Field(default=6379, description="Redis port")
|
||||
db: int = Field(default=0, description="Redis database number")
|
||||
password: Optional[str] = Field(default=None, description="Redis password")
|
||||
|
||||
# Pool settings
|
||||
max_connections: int = Field(default=20, description="Maximum Redis connections")
|
||||
socket_timeout: int = Field(default=5, description="Socket timeout in seconds")
|
||||
|
||||
# Cache settings
|
||||
default_ttl: int = Field(default=3600, description="Default cache TTL in seconds")
|
||||
key_prefix: str = Field(default="hcfs:", description="Redis key prefix")
|
||||
|
||||
class Config:
|
||||
env_prefix = "HCFS_REDIS_"
|
||||
|
||||
|
||||
class SecurityConfig(BaseSettings):
|
||||
"""Security configuration."""
|
||||
|
||||
# Authentication
|
||||
require_auth: bool = Field(default=True, description="Require authentication")
|
||||
api_key_header: str = Field(default="X-API-Key", description="API key header name")
|
||||
|
||||
# Rate limiting
|
||||
rate_limit_enabled: bool = Field(default=True, description="Enable rate limiting")
|
||||
rate_limit_storage: str = Field(default="memory", description="Rate limit storage (memory/redis)")
|
||||
|
||||
# HTTPS settings
|
||||
force_https: bool = Field(default=False, description="Force HTTPS in production")
|
||||
hsts_max_age: int = Field(default=31536000, description="HSTS max age")
|
||||
|
||||
# Request validation
|
||||
max_request_size: int = Field(default=10 * 1024 * 1024, description="Maximum request size in bytes")
|
||||
max_query_params: int = Field(default=100, description="Maximum query parameters")
|
||||
|
||||
# Content security
|
||||
allowed_content_types: List[str] = Field(
|
||||
default=["application/json", "application/x-www-form-urlencoded", "multipart/form-data"],
|
||||
description="Allowed content types"
|
||||
)
|
||||
|
||||
class Config:
|
||||
env_prefix = "HCFS_SECURITY_"
|
||||
|
||||
|
||||
class HCFSConfig(BaseSettings):
|
||||
"""Main HCFS configuration combining all subsystem configs."""
|
||||
|
||||
# Environment
|
||||
environment: str = Field(default="development", description="Environment (development/staging/production)")
|
||||
debug: bool = Field(default=False, description="Enable debug mode")
|
||||
|
||||
# Application info
|
||||
app_name: str = Field(default="HCFS API", description="Application name")
|
||||
app_version: str = Field(default="2.0.0", description="Application version")
|
||||
app_description: str = Field(default="Context-Aware Hierarchical Context File System API", description="App description")
|
||||
|
||||
# Configuration file path
|
||||
config_file: Optional[str] = Field(default=None, description="Path to configuration file")
|
||||
|
||||
# Subsystem configurations
|
||||
database: DatabaseConfig = Field(default_factory=DatabaseConfig)
|
||||
embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
|
||||
api: APIConfig = Field(default_factory=APIConfig)
|
||||
monitoring: MonitoringConfig = Field(default_factory=MonitoringConfig)
|
||||
redis: RedisConfig = Field(default_factory=RedisConfig)
|
||||
security: SecurityConfig = Field(default_factory=SecurityConfig)
|
||||
|
||||
class Config:
|
||||
env_prefix = "HCFS_"
|
||||
env_file = ".env"
|
||||
env_file_encoding = "utf-8"
|
||||
|
||||
@validator('environment')
|
||||
def validate_environment(cls, v):
|
||||
"""Validate environment value."""
|
||||
allowed = ['development', 'staging', 'production']
|
||||
if v not in allowed:
|
||||
raise ValueError(f'Environment must be one of: {allowed}')
|
||||
return v
|
||||
|
||||
@validator('debug')
|
||||
def validate_debug_in_production(cls, v, values):
|
||||
"""Ensure debug is disabled in production."""
|
||||
if values.get('environment') == 'production' and v:
|
||||
raise ValueError('Debug mode cannot be enabled in production')
|
||||
return v
|
||||
|
||||
def is_production(self) -> bool:
|
||||
"""Check if running in production environment."""
|
||||
return self.environment == 'production'
|
||||
|
||||
def is_development(self) -> bool:
|
||||
"""Check if running in development environment."""
|
||||
return self.environment == 'development'
|
||||
|
||||
def get_database_url(self) -> str:
|
||||
"""Get database URL."""
|
||||
return f"sqlite:///{self.database.db_path}"
|
||||
|
||||
def get_redis_url(self) -> str:
|
||||
"""Get Redis URL."""
|
||||
if self.redis.password:
|
||||
return f"redis://:{self.redis.password}@{self.redis.host}:{self.redis.port}/{self.redis.db}"
|
||||
return f"redis://{self.redis.host}:{self.redis.port}/{self.redis.db}"
|
||||
|
||||
def load_from_file(self, config_path: str) -> None:
|
||||
"""Load configuration from YAML file."""
|
||||
import yaml
|
||||
|
||||
config_file = Path(config_path)
|
||||
if not config_file.exists():
|
||||
raise FileNotFoundError(f"Configuration file not found: {config_path}")
|
||||
|
||||
with open(config_file, 'r') as f:
|
||||
config_data = yaml.safe_load(f)
|
||||
|
||||
# Update configuration
|
||||
for key, value in config_data.items():
|
||||
if hasattr(self, key):
|
||||
setattr(self, key, value)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert configuration to dictionary."""
|
||||
return self.dict()
|
||||
|
||||
def save_to_file(self, config_path: str) -> None:
|
||||
"""Save configuration to YAML file."""
|
||||
import yaml
|
||||
|
||||
config_data = self.to_dict()
|
||||
|
||||
with open(config_path, 'w') as f:
|
||||
yaml.dump(config_data, f, default_flow_style=False, indent=2)
|
||||
|
||||
|
||||
# Global configuration instance
|
||||
config = HCFSConfig()
|
||||
|
||||
|
||||
def get_config() -> HCFSConfig:
|
||||
"""Get the global configuration instance."""
|
||||
return config
|
||||
|
||||
|
||||
def load_config(config_path: Optional[str] = None, **overrides) -> HCFSConfig:
|
||||
"""Load configuration with optional file and overrides."""
|
||||
global config
|
||||
|
||||
# Load from file if provided
|
||||
if config_path:
|
||||
config.load_from_file(config_path)
|
||||
|
||||
# Apply overrides
|
||||
for key, value in overrides.items():
|
||||
if hasattr(config, key):
|
||||
setattr(config, key, value)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def create_config_template(output_path: str = "hcfs_config.yaml") -> None:
|
||||
"""Create a configuration template file."""
|
||||
template_config = HCFSConfig()
|
||||
template_config.save_to_file(output_path)
|
||||
print(f"Configuration template created: {output_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Create configuration template
|
||||
create_config_template()
|
||||
Reference in New Issue
Block a user