feat: 云厂商SDK适配层(Vultr/DO/Cloudflare/阿里云/腾讯云)+ 同步服务 + 测试连接/同步接口与前端

This commit is contained in:
gouki
2026-08-02 15:56:48 +00:00
parent cc7b2c67fe
commit 1aacf51bea
13 changed files with 930 additions and 3 deletions
+101
View File
@@ -0,0 +1,101 @@
"""云厂商 SDK 适配层 — 抽象基类与标准化数据结构
各云厂商适配器继承 BaseAdapter,实现统一接口,将平台特定的 API 返回
转换为标准化的资产结构(NormalizedVPS / NormalizedDomain / AccountInfo),
供同步服务写入数据库。这样上层逻辑无需关心各平台 API 差异。
"""
from abc import ABC, abstractmethod
from dataclasses import asdict, dataclass, field
from typing import Optional
@dataclass
class NormalizedVPS:
"""标准化的 VPS 实例"""
external_id: str
name: str
ip_address: Optional[str] = None
region: Optional[str] = None
os: Optional[str] = None
cpu_cores: Optional[int] = None
memory_gb: Optional[float] = None
disk_gb: Optional[int] = None
status: str = "active"
monthly_cost: Optional[float] = None
currency: str = "USD"
raw: dict = field(default_factory=dict)
def to_dict(self) -> dict:
return asdict(self)
@dataclass
class NormalizedDomain:
"""标准化的域名"""
external_id: str
domain_name: str
registrar: Optional[str] = None
expiry_date: Optional[str] = None # ISO 日期字符串 YYYY-MM-DD
status: str = "active"
raw: dict = field(default_factory=dict)
def to_dict(self) -> dict:
return asdict(self)
@dataclass
class AccountInfo:
"""标准化的账户信息"""
balance: Optional[float] = None
currency: str = "USD"
pending_charges: Optional[float] = None
raw: dict = field(default_factory=dict)
def to_dict(self) -> dict:
return asdict(self)
def _overridden(instance: "BaseAdapter", method_name: str) -> bool:
"""判断子类是否重写了某方法(用于能力探测)"""
return type(instance).__dict__.get(method_name) is not None
class BaseAdapter(ABC):
"""云厂商适配器抽象基类
子类需:
- 通过 @register("xxx-sdk") 注册到注册表
- 设置 required_config(所需凭证字段,供前端表单提示)
- 实现 test_connection;按需重写 list_vps / list_domains / get_account
"""
#: 适配器所需的配置字段名(如 ["api_key"] 或 ["access_key_id", "access_key_secret"]
required_config: list = []
def __init__(self, config: Optional[dict] = None):
self.config = config or {}
@abstractmethod
def test_connection(self) -> dict:
"""测试连接 / 凭证有效性,返回 {"ok": bool, "message": str, ...}"""
def list_vps(self) -> list:
raise NotImplementedError(f"{type(self).__name__} 未实现 list_vps")
def list_domains(self) -> list:
raise NotImplementedError(f"{type(self).__name__} 未实现 list_domains")
def get_account(self) -> AccountInfo:
raise NotImplementedError(f"{type(self).__name__} 未实现 get_account")
def capabilities(self) -> dict:
"""返回适配器实际支持的能力(是否重写了相应方法)"""
return {
"list_vps": _overridden(self, "list_vps"),
"list_domains": _overridden(self, "list_domains"),
"get_account": _overridden(self, "get_account"),
}