"""Vultr 适配器(REST API v2,Bearer Token) API 文档:https://www.vultr.com/api/ 所需配置:{"api_key": "..."} """ import httpx from app.adapters.base import ( AccountInfo, BaseAdapter, NormalizedDomain, NormalizedVPS, ) from app.adapters.registry import register @register("vultr-api") class VultrAdapter(BaseAdapter): required_config = ["api_key"] BASE = "https://api.vultr.com/v2" def _headers(self) -> dict: return {"Authorization": f"Bearer {self.config.get('api_key', '')}"} def _get(self, path: str) -> dict: with httpx.Client(timeout=30) as client: resp = client.get(self.BASE + path, headers=self._headers()) resp.raise_for_status() return resp.json() def test_connection(self) -> dict: try: data = self._get("/account") balance = data.get("account", {}).get("balance") return {"ok": True, "message": f"连接成功,账户余额 {balance} USD"} except httpx.HTTPStatusError as e: return {"ok": False, "message": f"HTTP {e.response.status_code}:API Key 无效或权限不足"} except Exception as e: # noqa: BLE001 return {"ok": False, "message": str(e)} def get_account(self) -> AccountInfo: acc = self._get("/account").get("account", {}) return AccountInfo( balance=acc.get("balance"), currency="USD", pending_charges=acc.get("pending_charges"), raw=acc, ) def list_vps(self) -> list: data = self._get("/instances") result = [] for inst in data.get("instances", []): ram_mb = inst.get("ram") or 0 result.append( NormalizedVPS( external_id=inst.get("id"), name=inst.get("label") or inst.get("id"), ip_address=inst.get("main_ip"), region=inst.get("region"), os=inst.get("os"), cpu_cores=inst.get("vcpu_count"), memory_gb=round(ram_mb / 1024, 1) if ram_mb else None, disk_gb=inst.get("disk"), status="active" if inst.get("status") == "active" else (inst.get("status") or "unknown"), monthly_cost=inst.get("monthly_cost"), currency="USD", raw=inst, ) ) return result def list_domains(self) -> list: data = self._get("/domains") return [ NormalizedDomain( external_id=d.get("domain"), domain_name=d.get("domain"), registrar="vultr", raw=d, ) for d in data.get("domains", []) ]