from __future__ import annotations import os from dataclasses import dataclass from functools import lru_cache from pathlib import Path from urllib.parse import urlparse def _csv(value: str | None, fallback: list[str]) -> list[str]: if not value: return fallback return [item.strip() for item in value.split(",") if item.strip()] def _csv_with_defaults(value: str | None, defaults: list[str]) -> list[str]: items = _csv(value, []) seen = set(items) for item in defaults: if item not in seen: items.append(item) seen.add(item) return items def _default_allowed_download_hosts(base_url: str) -> list[str]: parsed = urlparse(base_url) if parsed.hostname: return [parsed.hostname] return ["package.pnkr.cloud"] @dataclass(frozen=True) class Settings: agent_version: str host: str port: int robot_package_base_url: str allowed_origins: list[str] allowed_download_hosts: list[str] allowed_docker_registries: list[str] cache_dir: Path app_dir: Path log_dir: Path db_path: Path allow_remove: bool allow_purge: bool allow_docker: bool allow_docker_compose: bool auto_install_docker: bool command_timeout_seconds: int def _bool(name: str, default: bool) -> bool: value = os.getenv(name) if value is None: return default return value.strip().lower() in {"1", "true", "yes", "on"} @lru_cache(maxsize=1) def get_settings() -> Settings: robot_package_base_url = os.getenv("ROBOT_PACKAGE_BASE_URL", "https://package.pnkr.cloud").rstrip("/") return Settings( agent_version=os.getenv("AGENT_VERSION", "1.0.0"), host=os.getenv("AGENT_HOST", "0.0.0.0"), port=int(os.getenv("AGENT_PORT", "5010")), robot_package_base_url=robot_package_base_url, allowed_origins=_csv( os.getenv("ALLOWED_ORIGINS"), [ "https://app.pnkr.cloud", "https://package.pnkr.cloud", "http://localhost:3000", "http://127.0.0.1:3000", "http://localhost:5173", "http://127.0.0.1:5173", "http://localhost:8080", "http://127.0.0.1:8080", ], ), allowed_download_hosts=_csv( os.getenv("ALLOWED_DOWNLOAD_HOSTS"), _default_allowed_download_hosts(robot_package_base_url), ), allowed_docker_registries=_csv_with_defaults( os.getenv("ALLOWED_DOCKER_REGISTRIES"), ["registry.robot.package", "docker.io"], ), cache_dir=Path(os.getenv("CACHE_DIR", "/var/cache/local-installer-agent/packages")), app_dir=Path(os.getenv("APP_DIR", "/opt/robot-apps")), log_dir=Path(os.getenv("LOG_DIR", "/var/log/local-installer-agent")), db_path=Path(os.getenv("DB_PATH", "/var/lib/local-installer-agent/agent.db")), allow_remove=_bool("ALLOW_REMOVE", True), allow_purge=_bool("ALLOW_PURGE", False), allow_docker=_bool("ALLOW_DOCKER", True), allow_docker_compose=_bool("ALLOW_DOCKER_COMPOSE", False), auto_install_docker=_bool("AUTO_INSTALL_DOCKER", True), command_timeout_seconds=int(os.getenv("COMMAND_TIMEOUT_SECONDS", "900")), ) settings = get_settings()