288 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| 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() | 
