"""Configuration management for the Netdata Zulip bot.""" import os from pathlib import Path from typing import Optional import structlog from dotenv import load_dotenv from .models import ZulipConfig, ServerConfig logger = structlog.get_logger() def load_config() -> tuple[ZulipConfig, ServerConfig]: """Load configuration from environment variables and .env files.""" # Load .env file if present env_file = Path(".env") if env_file.exists(): load_dotenv(env_file) logger.info("Loaded configuration from .env file") # Load Zulip configuration zulip_config = ZulipConfig( site=os.getenv("ZULIP_SITE", ""), email=os.getenv("ZULIP_EMAIL", ""), api_key=os.getenv("ZULIP_API_KEY", ""), stream=os.getenv("ZULIP_STREAM", "netdata-alerts"), ) # Validate required Zulip settings if not all([zulip_config.site, zulip_config.email, zulip_config.api_key]): raise ValueError( "Missing required Zulip configuration. Please set ZULIP_SITE, " "ZULIP_EMAIL, and ZULIP_API_KEY environment variables." ) # Load server configuration server_config = ServerConfig( host=os.getenv("SERVER_HOST", "0.0.0.0"), port=int(os.getenv("SERVER_PORT", "8443")), domain=os.getenv("SERVER_DOMAIN", ""), cert_path=os.getenv("SERVER_CERT_PATH", "/etc/letsencrypt/live"), enable_mtls=os.getenv("SERVER_ENABLE_MTLS", "true").lower() == "true", ) # Validate required server settings if not server_config.domain: raise ValueError( "Missing required server configuration. Please set SERVER_DOMAIN " "environment variable." ) logger.info( "Configuration loaded", zulip_site=zulip_config.site, zulip_email=zulip_config.email, zulip_stream=zulip_config.stream, server_host=server_config.host, server_port=server_config.port, server_domain=server_config.domain, mtls_enabled=server_config.enable_mtls, ) return zulip_config, server_config def load_zuliprc_config(zuliprc_path: Optional[str] = None) -> ZulipConfig: """Load Zulip configuration from a zuliprc file. Args: zuliprc_path: Path to zuliprc file. If None, looks for ~/.zuliprc Returns: ZulipConfig instance """ if zuliprc_path is None: zuliprc_path = Path.home() / ".zuliprc" else: zuliprc_path = Path(zuliprc_path) if not zuliprc_path.exists(): raise FileNotFoundError(f"Zuliprc file not found: {zuliprc_path}") config = {} with open(zuliprc_path, 'r') as f: for line in f: line = line.strip() if line and not line.startswith('#') and '=' in line: key, value = line.split('=', 1) config[key.strip()] = value.strip() # Map zuliprc keys to our config zulip_config = ZulipConfig( site=config.get('site', ''), email=config.get('email', ''), api_key=config.get('key', ''), stream=config.get('stream', 'netdata-alerts'), ) logger.info( "Loaded Zulip configuration from zuliprc", path=str(zuliprc_path), site=zulip_config.site, email=zulip_config.email, stream=zulip_config.stream ) return zulip_config