"""Cloudflared binary discovery and download helpers.""" import os import platform import shutil import stat from urllib import error as urlerror from urllib import request from ..logging import debug_log def _get_project_root(): return os.path.dirname(os.path.dirname(os.path.dirname(__file__))) def _get_cloudflared_dir(): return os.path.join(_get_project_root(), "bin") def _get_platform_binary_name(): system = platform.system().lower() machine = platform.machine().lower() if system == "windows": if "arm" in machine: return "cloudflared-windows-arm64.exe" return "cloudflared-windows-amd64.exe" if system == "darwin": if machine in ("arm64", "aarch64"): return "cloudflared-darwin-arm64" return "cloudflared-darwin-amd64" if system == "linux": if machine in ("arm64", "aarch64"): return "cloudflared-linux-arm64" return "cloudflared-linux-amd64" raise RuntimeError(f"Unsupported platform for cloudflared: {system}/{machine}") def _get_binary_path(bin_dir=None): bin_dir = bin_dir or _get_cloudflared_dir() binary_name = "cloudflared.exe" if platform.system().lower() == "windows" else "cloudflared" return os.path.join(bin_dir, binary_name) def _download_cloudflared(): asset = _get_platform_binary_name() url = f"https://github.com/cloudflare/cloudflared/releases/latest/download/{asset}" bin_dir = _get_cloudflared_dir() os.makedirs(bin_dir, exist_ok=True) target_path = _get_binary_path(bin_dir) debug_log(f"Downloading cloudflared from {url}") try: with request.urlopen(url, timeout=30) as resp: with open(target_path, "wb") as f: shutil.copyfileobj(resp, f) except urlerror.URLError as exc: raise RuntimeError(f"Failed to download cloudflared: {exc}") from exc st = os.stat(target_path) os.chmod(target_path, st.st_mode | stat.S_IEXEC) debug_log(f"Downloaded cloudflared to {target_path}") return target_path def ensure_binary() -> str: """Return a usable cloudflared binary path, downloading if necessary.""" env_path = os.environ.get("CLOUDFLARED_PATH") if env_path and os.path.exists(env_path): return env_path local_candidate = _get_binary_path() if os.path.exists(local_candidate): return local_candidate path_binary = shutil.which("cloudflared") if path_binary: return path_binary return _download_cloudflared()