DDNS

DDNS 配置系统开发文档

本文档面向开发者,详细说明如何扩展和修改 DDNS 配置系统。

系统架构

DDNS 配置系统采用分层架构,支持多种配置源:

┌─────────────────────────────────────────────┐
│               配置源(优先级)                │
├─────────────────────────────────────────────┤
│ CLI 参数 > JSON 文件 > 环境变量 > 默认值      │
├─────────────────────────────────────────────┤
│                Config 类                     │
│            统一配置访问接口                   │
├─────────────────────────────────────────────┤
│            Provider 和应用模块               │
└─────────────────────────────────────────────┘

核心模块:

Config 类核心实现

Config 类是配置系统的核心,负责合并多个配置源:

class Config(object):
    def __init__(self, cli_config=None, json_config=None, env_config=None):
        self._cli_config = cli_config or {}
        self._json_config = json_config or {}  
        self._env_config = env_config or {}
        
        # 配置属性初始化
        self.dns = self._get("dns", "debug")
        self.endpoint = self._get("endpoint")  # 新增的端点配置
        
    def _get(self, key, default=None):
        """按优先级获取配置值:CLI > JSON > ENV > default"""
        return (
            self._cli_config.get(key) or 
            self._json_config.get(key) or 
            self._env_config.get(key) or 
            default
        )

配置参数概览

必需参数

主要参数

支持的 DNS 服务商

SUPPORTED_PROVIDERS = [
    "alidns", "callback", "cloudflare", "debug", "dnscom", 
    "dnspod_com", "dnspod", "he", "huaweidns", "noip", "tencentcloud"
]

开发指南:添加新配置参数

完整开发流程

添加新配置参数需要修改 4 个文件:

1. 更新 JSON Schema (schema/v4.0.json)

{
  "properties": {
    "my_param": {
      "type": "string",
      "title": "My Parameter", 
      "description": "Description of my parameter",
      "default": "default_value"
    }
  }
}

2. 添加 CLI 参数 (ddns/config/cli.py)

def create_parser(description, doc, version, date):
    # ...existing code...
    parser.add_argument(
        "--my-param",
        help="Description of my parameter",
        default=None
    )

3. 更新 Config 类 (ddns/config/config.py)

class Config(object):
    def __init__(self, cli_config=None, json_config=None, env_config=None):
        # ...existing code...
        self.my_param = self._get("my_param", "default_value")
        
    def dict(self):
        return {
            # ...existing fields...
            "my_param": self.my_param,
        }

4. 添加单元测试 (tests/test_config_config.py)

def test_my_param_configuration(self):
    """Test my_param configuration from different sources"""
    # CLI 配置测试
    config = Config(cli_config={"my_param": "cli_value"})
    self.assertEqual(config.my_param, "cli_value")
    
    # JSON 配置测试
    config = Config(json_config={"my_param": "json_value"})
    self.assertEqual(config.my_param, "json_value")
    
    # 优先级测试
    config = Config(
        cli_config={"my_param": "cli_value"},
        json_config={"my_param": "json_value"}
    )
    self.assertEqual(config.my_param, "cli_value")  # CLI 优先

环境变量支持

新参数自动支持环境变量,命名规则:DDNS_PARAM_NAME

export DDNS_MY_PARAM=value

特殊类型处理

数组参数

需要在 SIMPLE_ARRAY_PARAMS 中注册:

# config.py
SIMPLE_ARRAY_PARAMS = ["ipv4", "ipv6", "proxy", "my_array_param"]

def split_array_string(value):
    """支持多种分隔符:逗号、分号"""
    if isinstance(value, list):
        return value
    # 支持 "a,b" 或 "a;b" 格式
    if "," in str(value):
        return [item.strip() for item in value.split(",")]
    elif ";" in str(value):
        return [item.strip() for item in value.split(";")]
    return [value]

布尔值处理

使用 str_bool() 函数:

def str_bool(value):
    """将字符串转换为布尔值"""
    if isinstance(value, bool):
        return value
    if str(value).lower() in ["true", "yes", "1", "on"]:
        return True
    if str(value).lower() in ["false", "no", "0", "off"]:
        return False
    return bool(value)

类型转换示例

# 在 Config.__init__ 中
self.ttl = int(self._get("ttl")) if self._get("ttl") else None
self.cache = str_bool(self._get("cache", True))
self.proxy = self._get("proxy", [])  # 自动处理数组

配置使用示例

CLI 基本用法

python -m ddns --dns=cloudflare --endpoint=https://api.custom.com/v4/

JSON 配置

{
  "dns": "cloudflare",
  "endpoint": "https://api.custom.com/v4/",
  "ipv4": ["example.com"]
}

环境变量

export DDNS_DNS=cloudflare
export DDNS_ENDPOINT=https://api.custom.com/v4/

开发和调试

配置验证

def validate_config(config):
    """验证配置完整性"""
    errors = []
    
    if not config.id or not config.token:
        errors.append("id and token are required")
        
    if config.dns not in SUPPORTED_DNS_PROVIDERS:
        errors.append("Unsupported DNS provider: {}".format(config.dns))
    
    if config.ttl and (config.ttl < 1 or config.ttl > 86400):
        errors.append("TTL must be between 1 and 86400 seconds")
            
    return errors

配置调试

def debug_config(config):
    """输出配置信息(隐藏敏感数据)"""
    config_dict = config.dict()
    for key, value in config_dict.items():
        if key == "token" and value:
            value = value[:2] + "***" + value[-2:]
        print("{}: {}".format(key, value))

开发测试

# 运行配置相关测试
python -m unittest discover tests -k "test_config" -v

# 测试特定功能
python -m unittest tests.test_config_config.TestConfigPriority -v

测试工具

def create_test_config(**overrides):
    """创建测试配置"""
    default_config = {
        "dns": "debug",
        "id": "test_id", 
        "token": "test_token"
    }
    default_config.update(overrides)
    return Config(json_config=default_config)

# 使用
config = create_test_config(dns="cloudflare", endpoint="https://api.test.com")

开发最佳实践

添加新参数的检查清单

  1. JSON Schema - 在 schema/v4.0.json 中定义
  2. CLI 参数 - 在 cli.py 中添加 --param-name
  3. Config 类 - 在 config.py 中添加属性和 dict() 方法
  4. 单元测试 - 测试配置优先级和类型转换
  5. 向后兼容 - 提供合理的默认值

代码规范

endpoint 参数特性

endpoint 参数是 v4.0 新增功能,主要用于:

配置系统架构优势

通过这个配置系统,开发者可以快速添加新功能参数,保持代码的一致性和可维护性。