119 lines
4.3 KiB
Python
119 lines
4.3 KiB
Python
import json
|
||
import os
|
||
import subprocess
|
||
import requests
|
||
from typing import Dict, Optional, Tuple
|
||
from ..utils.crypto import encrypt, decrypt
|
||
|
||
|
||
class ConfigManager:
|
||
"""配置文件管理器"""
|
||
|
||
def __init__(self, storage_path: str = "ab", cdn_base_url: str = ""):
|
||
self.storage_path = storage_path
|
||
self.cdn_base_url = cdn_base_url
|
||
|
||
def version_to_path(self, version: str) -> str:
|
||
"""将版本号转换为存储路径格式"""
|
||
# 0.29 -> 0_29
|
||
return version.replace('.', '_')
|
||
|
||
def get_config_path(self, version: str, platform: str) -> str:
|
||
"""获取配置文件在对象存储中的路径"""
|
||
version_path = self.version_to_path(version)
|
||
filename = f"{platform}config.json"
|
||
return f"{self.storage_path}/{version_path}/{filename}"
|
||
|
||
def get_cdn_url(self, version: str, platform: str) -> str:
|
||
"""获取配置文件在CDN中的URL"""
|
||
if not self.cdn_base_url:
|
||
return ""
|
||
version_path = self.version_to_path(version)
|
||
filename = f"{platform}config.json"
|
||
return f"{self.cdn_base_url}/{self.storage_path}/{version_path}/{filename}"
|
||
|
||
def download_from_storage(self, version: str, platform: str) -> Optional[str]:
|
||
"""从对象存储下载并解密配置文件"""
|
||
try:
|
||
config_path = self.get_config_path(version, platform)
|
||
|
||
# 使用rclone下载文件
|
||
result = subprocess.run(
|
||
["rclone", "cat", config_path],
|
||
capture_output=True,
|
||
text=True,
|
||
timeout=30
|
||
)
|
||
|
||
if result.returncode != 0:
|
||
print(f"警告: 无法从对象存储下载 {config_path}: {result.stderr}")
|
||
return None
|
||
|
||
# 解密文件内容
|
||
encrypted_content = result.stdout.strip()
|
||
if not encrypted_content:
|
||
print(f"警告: 文件 {config_path} 为空")
|
||
return None
|
||
|
||
decrypted_content = decrypt(encrypted_content)
|
||
return decrypted_content
|
||
|
||
except subprocess.TimeoutExpired:
|
||
print(f"错误: 下载 {config_path} 超时")
|
||
return None
|
||
except Exception as e:
|
||
print(f"错误: 下载 {config_path} 失败: {str(e)}")
|
||
return None
|
||
|
||
def get_from_cdn(self, version: str, platform: str) -> Optional[str]:
|
||
"""从CDN获取配置文件内容"""
|
||
try:
|
||
cdn_url = self.get_cdn_url(version, platform)
|
||
if not cdn_url:
|
||
print(f"警告: CDN URL未配置,跳过CDN内容获取")
|
||
return None
|
||
|
||
response = requests.get(cdn_url, timeout=10)
|
||
response.raise_for_status()
|
||
|
||
# CDN中的内容应该是解密后的JSON
|
||
return response.text
|
||
|
||
except requests.RequestException as e:
|
||
print(f"警告: 无法从CDN获取 {cdn_url}: {str(e)}")
|
||
return None
|
||
except Exception as e:
|
||
print(f"错误: 获取CDN内容失败: {str(e)}")
|
||
return None
|
||
|
||
def parse_config(self, content: str) -> Optional[Dict]:
|
||
"""解析配置文件内容"""
|
||
try:
|
||
return json.loads(content)
|
||
except json.JSONDecodeError as e:
|
||
print(f"错误: 配置文件格式错误: {str(e)}")
|
||
return None
|
||
|
||
def compare_configs(self, storage_config: Dict, cdn_config: Dict) -> Dict:
|
||
"""比较存储配置和CDN配置的差异"""
|
||
all_keys = set(storage_config.keys()) | set(cdn_config.keys())
|
||
differences = {}
|
||
|
||
for key in sorted(all_keys):
|
||
storage_value = storage_config.get(key, "N/A")
|
||
cdn_value = cdn_config.get(key, "N/A")
|
||
|
||
if storage_value != cdn_value:
|
||
differences[key] = {
|
||
"storage": storage_value,
|
||
"cdn": cdn_value,
|
||
"different": True
|
||
}
|
||
else:
|
||
differences[key] = {
|
||
"storage": storage_value,
|
||
"cdn": cdn_value,
|
||
"different": False
|
||
}
|
||
|
||
return differences |