* Initial plan * feat(docs): add static documentation website builder script Add build_docs.py script to convert markdown docs to static HTML website with: - Responsive navigation bar with collapsible directory tree - In-page table of contents (right sidebar, hidden on small screens) - Language switcher (Chinese/English) - Pure static HTML output (no server-side processing) - Footer with GitHub links and edit page link - Mobile-friendly responsive design Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * style: format build_docs.py with ruff Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): use MkDocs with Material theme instead of custom parser Replace custom markdown parser with industry-standard tools: - MkDocs: Popular static site generator for documentation - Material for MkDocs: Modern, feature-rich theme Benefits: - Mature, well-tested codebase used by thousands of projects - Built-in features: search, navigation, TOC, code highlighting - Active development with regular updates - Extensive documentation and community support - Beautiful, responsive design out of the box - Easy to maintain with configuration-based approach Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): use VitePress instead of MkDocs for documentation Replace MkDocs with VitePress - a Vue-powered static site generator: - VitePress: Modern, fast, designed for documentation - Vue 3 + Vite stack with instant HMR - Built-in i18n, search, dark mode, responsive design - Chinese-friendly (created by Evan You) Features: - Responsive navigation with collapsible sidebar - In-page TOC automatically generated - Bilingual support (Chinese/English) - Local search with keyboard shortcuts - Light/Dark mode toggle - Edit page links to GitHub - Pure static HTML output Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * feat(docs): add automated setup and build with npm run build Add automated directory setup for VitePress build: - Created scripts/setup-docs.mjs to auto-setup docs structure - Updated package.json with 'build' command that runs setup + build - Updated docs:dev to include setup automatically - Simplified workflow to one command: npm run build Changes: - npm run build now handles everything automatically - No need for separate bash script - Directory structure created on-demand - Updated BUILD_DOCS.md with simplified instructions Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): improve VitePress configuration per feedback Addressed all feedback items: 1. Fixed edit link mapping: index.html now correctly maps to README.md/README.en.md in GitHub 2. Added schema directory to build output via public/ directory 3. Removed /doc/ prefix from all URLs - doc/ is now the web root 4. Fixed path references in README files during setup Changes: - Updated editLink to use function for proper README mapping - Modified setup script to copy doc/ contents to docs root (not docs/doc/) - Added schema/ to public/ directory for static asset serving - Fixed /doc/ path references in copied README files - Updated all navigation and sidebar paths to remove /doc/ prefix URLs now work as: - / (homepage from README.md) - /docker, /install (no /doc/ prefix) - /config/cli, /providers/dnspod (clean paths) - /schema/v4.0.json (accessible in build) Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): preserve original /doc/ paths in documentation Per user feedback, reverted path modifications: - No longer replace /doc/ paths in README files - Restored doc/ directory structure (docs/doc/) - Updated VitePress navigation to use /doc/ prefix - Edit links correctly map to source files in doc/ directory Changes: - setup-docs.mjs: removed path replacement, copy doc/ to docs/doc/ - config.mts: restored /doc/ prefix in all navigation and sidebar paths - URLs now match original documentation: /doc/docker, /doc/providers/dnspod This preserves the original documentation structure and paths as they appear in the source repository. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): remove /doc/ prefix from URLs and ignore intermediate files Per user feedback, changed URLs from /doc/xxx.html to /xxx.html: Changes: 1. Updated setup-docs.mjs to copy doc/ contents to docs/ root (not docs/doc/) 2. Modified path replacement to handle both links and image src attributes 3. Updated VitePress config.mts to remove /doc/ prefix from all nav/sidebar paths 4. Updated .gitignore to exclude intermediate copied files from commits 5. Removed docs/index.md and docs/en/index.md from git tracking URLs now: - /docker.html instead of /doc/docker.html - /providers/dnspod.html instead of /doc/providers/dnspod.html - /config/cli.html instead of /doc/config/cli.html - Images at /img/ddns.svg instead of /doc/img/ddns.svg - Schema files remain at /schema/v4.0.json Intermediate files generated during build are now gitignored and won't be committed. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): move build scripts to doc/ directory Moved documentation build scripts from root and scripts/ to doc/ directory: - Moved scripts/setup-docs.mjs → doc/setup-docs.mjs - Moved build_docs.sh → doc/build_docs.sh - Removed empty scripts/ directory - Updated package.json to reference new script locations - Updated BUILD_DOCS.md with new directory structure This organizes all documentation-related files under doc/ directory, keeping the repository root cleaner. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): consolidate into single doc/ directory Eliminated docs/ directory, consolidated everything under doc/: - Moved docs/.vitepress/ → doc/.vitepress/ - Removed docs/ directory entirely - Updated package.json to use doc/ instead of docs/ - Updated .gitignore to reflect new structure (doc/.vitepress/dist/, doc/index.md, doc/en/, doc/public/) - Updated setup-docs.mjs to generate files within doc/ - Updated BUILD_DOCS.md documentation Structure now: - doc/ contains source files, VitePress config, and generated intermediate files - All build artifacts stay within doc/.vitepress/dist/ - Simpler single-directory structure without doc/docs nesting Commands remain the same: - npm run build - npm run docs:dev - npm run docs:preview Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): move package.json to doc/ directory Moved package.json to doc/ directory to consolidate all documentation-related files: - Moved package.json from root → doc/package.json - Updated package.json scripts to use relative paths (. instead of doc) - Updated BUILD_DOCS.md with new usage instructions (cd doc first) - Updated build_docs.sh to work from within doc/ directory - .gitignore already handles node_modules/ globally All documentation dependencies and configuration now in single doc/ directory. Usage: ```bash cd doc npm install npm run build ``` Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * feat(docs): add install.sh to public, auto-redirects, and ensure README→index.html mapping Implemented three enhancements: 1. Copy install.sh to public/ directory - install.sh now accessible at /install.sh in build - Users can download directly from documentation site 2. Add automatic redirects for old URLs - Created custom VitePress theme with redirect logic - /doc/xxx URLs redirect to /xxx - /doc/xxx.en.html URLs redirect to /en/xxx.html - Maintains backward compatibility with old links 3. README.md renders as index.html with correct edit links - Already configured: index.md maps to README.md for editing - en/index.md maps to README.en.md for editing - Edit links work correctly for both Chinese and English homepages Updated BUILD_DOCS.md with new features documentation. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * feat(docs): upgrade to VitePress 2.0 (next) Upgraded VitePress from v1.x to v2.0 (next tag): - Updated package.json to use "vitepress": "next" - Currently using v2.0.0-alpha.15 - Tested build successfully - all features working - Updated BUILD_DOCS.md to reflect VitePress 2.0 VitePress 2.0 benefits: - Better performance and faster build times - Improved developer experience - Enhanced features and bug fixes - Future-ready with latest Vue 3 + Vite improvements Build tested and confirmed working with no breaking changes. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): remove redundant build script and fix copyright years Changes per user feedback: 1. Removed doc/build_docs.sh (redundant - standard npm commands sufficient) 2. Updated copyright in config.mts line 133: "Copyright © 2016 ~ 2024 NewFuture" 3. Updated copyright in config.mts line 305: "Copyright © 2016 ~ 2024 NewFuture" Usage now simplified to standard npm commands: - cd doc && npm install - npm run build - npm run docs:dev - npm run docs:preview Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): dynamic copyright year, move redirects to esa.js, update providers link Per user feedback: 1. Made copyright year dynamic: `${new Date().getFullYear()}` (line 305) 2. Moved redirect logic from theme/index.ts to esa.js for server-side handling 3. Changed providers link from "概述 /providers/README" to "所有服务商 /providers/index" (line 70) Changes: - config.mts: Dynamic copyright calculation, updated providers navigation - esa.js: Added redirect logic for /doc/ URLs (301 permanent redirects) - theme/index.ts: Removed client-side redirect logic (now handled server-side) Redirects now handled at edge function level for better SEO and performance. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): improve redirects, provider link, and add code-to-GitHub link conversion Per user feedback (comment #3736692270): 1. Moved .en.html redirect logic before general /doc/ redirect in esa.js 2. Added /index.en.html → /en/ redirect 3. Changed providers/README URL to providers/ (line 39) 4. Added markdown transformer to convert code links (e.g., /ddns/provider/dnspod.py) to GitHub links Changes: - esa.js: Reordered redirect logic (en first), added index.en.html redirect - config.mts: Changed providers link from /providers/README to /providers/ - config.mts: Added markdown.config to transform inline code paths to GitHub links Code paths like `/ddns/provider/dnspod.py` in documentation will now automatically link to GitHub repository. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * feat(docs): enable dead link check, add sitemap, llms.txt, and GitHub Actions build Per user feedback (comment #3736806631): 1. Changed redirects to 301 permanent redirects in esa.js (line 183) 2. Enabled dead link checking in config.mts (ignoreDeadLinks: false) 3. Added sitemap generation (sitemap.hostname: https://ddns.newfuture.cc) 4. Added llms.txt generation via buildEnd hook for AI/LLM context 5. Created GitHub Actions workflow (.github/workflows/build-docs.yml) to build docs on push Changes: - esa.js: Clarified 301 redirect comment - config.mts: Enabled dead link check, added sitemap config, added buildEnd hook for llms.txt - .github/workflows/build-docs.yml: New workflow to build and optionally deploy docs GitHub Action triggers on: - Push to master/main (doc/, README*, schema/ paths) - Pull requests - Manual workflow dispatch Build output includes sitemap.xml and llms.txt for better SEO and AI integration. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): update Node.js to v24, retention to 7 days, simplify BUILD_DOCS Per user feedback (comment #3736833266): 1. Updated Node.js version from v20 to v24 in build-docs.yml (line 33) 2. Changed artifact retention from 30 to 7 days (line 50) 3. Simplified BUILD_DOCS.md - removed verbose explanations, kept essentials Changes: - .github/workflows/build-docs.yml: Node 24, 7-day retention - BUILD_DOCS.md: Condensed from 327 to 40 lines, focused on quick start and essential commands BUILD_DOCS.md now provides concise reference instead of lengthy tutorial. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * refactor(docs): simplify link transformer, extract llms.txt template, add docs agent Per user feedback (comment #3737275691): 1. Simplified markdown transformer to only process link (a tag) hrefs instead of code_inline tokens 2. Extracted llms.txt content to separate template file (doc/llms.txt) with: - Complete documentation structure with all page URLs - All schema file URLs (v4.0, v2.8, v2) - Template variable {{DATE}} for build-time replacement 3. Deleted BUILD_DOCS.md and created .github/agents/docs.agent.md: - Comprehensive documentation maintenance agent - Full guide for updating docs, navigation, providers - Build/test procedures and common tasks - Guidelines for writing and link handling Changes: - config.mts: Transform link hrefs (not inline code), read llms.txt from template - doc/llms.txt: New template with full doc/schema URLs - .github/agents/docs.agent.md: New documentation maintenance agent - BUILD_DOCS.md: Deleted (replaced by agent instructions) Link transformer now only modifies existing <a> tags, preserving markdown styling. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): add metadata to docs agent, fix markdown syntax, add v4.1.json schema Per user feedback (comment #3737334654): 1. Added YAML metadata to docs.agent.md (name, description) following new-provider.agent.md format 2. Fixed markdown syntax to be GitHub-compatible: - Changed inline code blocks in list items to properly formatted code blocks - Ensured all code examples are in fenced code blocks 3. Added missing v4.1.json schema to llms.txt (was only showing v4.0, v2.8, v2) Changes: - .github/agents/docs.agent.md: Added YAML frontmatter, fixed markdown formatting - doc/llms.txt: Added v4.1 schema URL (first in list as newest version) All schema files now documented: v4.1, v4.0, v2.8, v2 Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): restructure to docs/ directory with cleaner organization Per user feedback (comment #3737399407): 1. Renamed doc/ → docs/ 2. Moved all .en.md files → docs/en/*.md (removed .en suffix) 3. Moved install.sh → docs/install.sh (source file, not copied) 4. Moved favicon.ico → docs/favicon.ico (source file) 5. Simplified setup-docs.mjs - no longer copies English files or install.sh 6. Updated all path references: - GitHub Actions workflow: doc/ → docs/ - .gitignore: doc/ → docs/ - VitePress config: edit links now map to docs/ - Documentation agent: updated structure docs New Structure: - docs/ (was doc/) - config/, providers/, dev/ (Chinese markdown) - en/ (English markdown, no .en suffix) - config/, providers/, dev/ - install.sh (source) - favicon.ico (source) - llms.txt (template) Build command unchanged: cd docs && npm run build All English documentation now sourced directly from docs/en/ instead of being generated. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): update documentation links from /doc/ to docs/ in README files Per user feedback (comment #3737497400): 1. Updated setup-docs.mjs to properly replace /doc/ → docs/ → / in README processing 2. Updated all /doc/ links to docs/ in README.md: - Image src: /doc/img/ddns.svg → docs/img/ddns.svg - Docker docs: /doc/docker.md → docs/docker.md - Config docs: /doc/config/* → docs/config/* - Provider docs: /doc/providers/* → docs/providers/* 3. Updated all /doc/ links to docs/en/ in README.en.md: - Image src: /doc/img/ddns.svg → docs/img/ddns.svg - Docker docs: /doc/docker.en.md → docs/en/docker.md - Config docs: /doc/config/*.en.md → docs/en/config/*.md - Provider docs: /doc/providers/*.en.md → docs/en/providers/*.md Changes: - docs/setup-docs.mjs: Two-step replacement (/doc/ → docs/ → /) for GitHub links - README.md: All documentation links now use docs/ prefix - README.en.md: All documentation links now use docs/en/ prefix Verified: No /doc/ links remain in README files or .github markdown files. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): simplify setup script and move to .vitepress directory Per user feedback (comment #3737562776): 1. Moved setup-docs.mjs to docs/.vitepress/ directory 2. Simplified link replacement logic: - Removed unnecessary /doc/ processing code - Now only converts docs/ → / (Chinese version) - And docs/en/ → / (English version) - Since README files already use correct docs/ prefix 3. Updated package.json script paths to reference .vitepress/setup-docs.mjs 4. Updated path variables in script to work from .vitepress/ location Changes: - docs/.vitepress/setup-docs.mjs: New location, simplified logic - docs/package.json: Updated setup script path - Removed obsolete /doc/ → docs/ replacement steps Build process now simpler and cleaner. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): fix all broken documentation links Per user feedback (comment #3737640946): Fixed all broken links throughout the documentation: 1. Fixed providers/README links → providers/ (clean URL) 2. Removed all .en.md suffixes from links (files now in docs/en/ with .md extension) 3. Fixed /doc/ prefix references → proper docs/ paths 4. Fixed cross-references between Chinese and English docs: - Chinese providers/README.md → ../en/providers/*.md for English docs - English docs use relative paths within en/ directory 5. Fixed redirect_to URLs in dnscom.md files 6. Fixed image URL: /doc/img/ → /img/ Changes affect 28 files: - All config documentation (cli.md, env.md, json.md) in both languages - All provider documentation in both languages - Developer documentation (dev/config.md) - Docker documentation - Provider README files All dead links now resolved. Documentation navigation works correctly. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): fix remaining dead links in generated index.md and provider files Per user feedback (comment #3737692822): Fixed all remaining dead links: 1. Enhanced setup-docs.mjs to handle ./doc/ prefix links: - Added replacement for (./doc/ → (/ - Added replacement for /providers/index → /providers/ - Now correctly converts README links to clean web URLs 2. Fixed provider documentation links: - callback.md and debug.md: Added "Return to All Providers" links - English versions: Added /en/providers/ links - Removed broken ./../../README links All dead links now resolved: - ./doc/install → /install - ./doc/providers/* → /providers/* - ./doc/config/* → /config/* - /providers/index → /providers/ - Provider files now link to /providers/ and /en/providers/ Dead link checking should now pass successfully. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): fix all remaining dead links in documentation Per user feedback (comment #3737728554): Fixed all remaining dead links throughout documentation: 1. Enhanced setup-docs.mjs: - Added replacement for ](doc/ pattern - Handles more link format variations 2. Fixed config files (6 files): - config/cli.md: providers/ → ../providers/, providers/callback → ../providers/callback - config/json.md: docker.md → ../docker.md, providers/ → ../providers/ - en/config/env.md: providers/callback → ../providers/callback, docker → ../docker, providers/ → ../providers/ - en/config/json.md: docker.md → ../docker.md, providers/ → ../providers/ 3. Fixed provider files (6 files): - providers/callback.md, debug.md, README.md: ../../README.md → / - en/providers/callback.md, debug.md: ../../README.md → /en/ - en/providers/he.md: ../json.md → ../config/json.md All dead links resolved: ✓ ./providers/index → ../providers/ ✓ ./providers/callback → ../providers/callback ✓ ./docker → ../docker ✓ ./../../README → / (or /en/) ✓ ../json → ../config/json ✓ ](doc/ → ](/ Dead link checking should now pass successfully with zero errors. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): add VitePress rewrites to map providers/README.md to /providers/ Per user feedback (comment #3737780259): Fixed `/providers/index` dead links by adding VitePress rewrites configuration. Changes to docs/.vitepress/config.mts: 1. Added rewrites mapping: - providers/README.md → providers/index.md - en/providers/README.md → en/providers/index.md 2. Updated sidebar links: - /providers/index → /providers/ - /en/providers/index → /en/providers/ This tells VitePress that the README.md files in providers directories should be accessible via the /providers/ URL (with cleanUrls enabled). All /providers/index links now correctly resolve to /providers/ Dead link checking should now pass with zero errors. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): fix providers/index links and simplify setup script Per user feedback (comment #3737836475): 1. Fixed dead links in config/env.md files: - ./providers/ → ../providers/ (both Chinese and English) 2. Simplified setup-docs.mjs: - Removed unnecessary doc/ processing (README no longer contains doc/) - Merged logic for both README files into single processReadme function - Cleaner, more maintainable code with less duplication Changes: - docs/config/env.md: Fixed providers/ link - docs/en/config/env.md: Fixed providers/ link - docs/.vitepress/setup-docs.mjs: Refactored with shared function Dead link checking should now pass with zero errors. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): remove providers/index replacement from setup script Per user feedback (comment #3737887893): Removed `/providers/index` → `/providers/` replacement from setup-docs.mjs. This should be fixed in markdown files instead, not in the setup script. Simplified setup script by removing unnecessary transformation logic. Changes: - docs/.vitepress/setup-docs.mjs: Removed line 29 replacement Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): update remaining /doc/ references to docs/ in README files Per user feedback (comment #3737970179): Updated all remaining /doc/ references to docs/ or docs/en/ in both README files. Changes in README.md: - doc/install.md → docs/install.md - All doc/providers/*.md → docs/providers/*.md (10 provider links) Changes in README.en.md: - doc/install.en.md → docs/en/install.md - doc/providers/dnspod.en.md → docs/en/providers/dnspod.md - doc/providers/alidns.en.md → docs/en/providers/alidns.md All documentation links now correctly use docs/ prefix for GitHub navigation. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * fix(docs): update all remaining doc/ references to docs/ in README files Per user feedback (comment #3738298603): Updated ALL remaining doc/ references to docs/ or docs/en/ in both README files. Changes in README.md (13 links): - doc/providers/edgeone.md → docs/providers/edgeone.md - doc/providers/noip.md → docs/providers/noip.md - doc/config/cli.md → docs/config/cli.md (3 occurrences) - doc/config/json.md → docs/config/json.md (2 occurrences) - doc/config/env.md → docs/config/env.md (2 occurrences) - doc/providers/ → docs/providers/ (3 occurrences) Changes in README.en.md (13 links): - doc/providers/*.en.md → docs/en/providers/*.md (9 provider links) - doc/config/cli.en.md → docs/en/config/cli.md - doc/config/json.en.md → docs/en/config/json.md - doc/config/env.en.md → docs/en/config/env.md - doc/providers/ → docs/en/providers/ All documentation links now use correct docs/ prefix with NO /doc/ references remaining. Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * refactor(docs): integrate setup logic into config.mts Per user feedback (comment #3738600577): Integrated setup-docs.mjs functionality into config.mts. Changes: 1. Removed standalone setup-docs.mjs file 2. Added setupDocs() function in config.mts that runs before config export 3. Simplified package.json scripts - removed setup step 4. Setup now runs automatically when config loads (works for both dev and build) Benefits: - Single configuration file - easier to maintain - No separate setup script needed - Automatic execution on both dev and build - Cleaner package.json scripts - Same functionality, simpler implementation Build command: `npm run build` or `npm run docs:dev` Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> * update link * /doc/img/ddns.svg * fix docs paths * fix docs * fix docs url --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: NewFuture <6290356+NewFuture@users.noreply.github.com> Co-authored-by: New Future <NewFuture@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
11 KiB
DDNS Configuration System Development Documentation
This document is for developers, detailing how to extend and modify the DDNS configuration system.
System Architecture
The DDNS configuration system uses a layered architecture supporting multiple configuration sources:
┌─────────────────────────────────────────────┐
│ Configuration Sources (Priority) │
├─────────────────────────────────────────────┤
│ CLI Args > JSON File > Env Vars > Defaults │
├─────────────────────────────────────────────┤
│ Config Class │
│ Unified Configuration Interface │
├─────────────────────────────────────────────┤
│ Providers and App Modules │
└─────────────────────────────────────────────┘
Core Modules:
ddns/config/cli.py- Command line argument parsingddns/config/json.py- JSON configuration file handlingddns/config/env.py- Environment variable parsingddns/config/config.py- Config class implementation
Config Class Core Implementation
The Config class is the core of the configuration system, responsible for merging multiple configuration sources:
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 {}
# Configuration attribute initialization
self.dns = self._get("dns", "debug")
self.endpoint = self._get("endpoint") # New endpoint configuration
def _get(self, key, default=None):
"""Get configuration value by priority: CLI > JSON > ENV > default"""
return (
self._cli_config.get(key) or
self._json_config.get(key) or
self._env_config.get(key) or
default
)
Adding New Configuration Parameters
Step 1: Update JSON Schema
First, add the new parameter to the JSON schema files:
// schema/v4.0.json
{
"properties": {
"new_param": {
"type": "string",
"description": "Description of new parameter"
}
}
}
Step 2: Add CLI Parameter
Add command line parameter support in ddns/config/cli.py:
def load_config(description, doc, version, date):
parser = ArgumentParser(...)
# Add new parameter
parser.add_argument(
"--new-param",
dest="new_param",
help="Help text for new parameter"
)
Step 3: Add Environment Variable Support
Add environment variable parsing in ddns/config/env.py:
def load_config():
config = {}
# Add new parameter
config["new_param"] = os.getenv("DDNS_NEW_PARAM")
return config
Step 4: Update Config Class
Add the new attribute to the Config class in ddns/config/config.py:
class Config(object):
def __init__(self, ...):
# ... existing code ...
self.new_param = self._get("new_param")
Step 5: Update Documentation
Update the relevant documentation files:
config/cli.md- Add CLI parameter documentationconfig/env.md- Add environment variable documentationconfig/json.md- Add JSON configuration documentation
Configuration Value Processing
Type Conversion
The configuration system provides several utility functions for type conversion:
from ddns.config.cli import str_bool
# Boolean conversion
debug = str_bool(config.get("debug", False))
# List conversion
domains = config.get("ipv4", [])
if isinstance(domains, str):
domains = [d.strip() for d in domains.split(",") if d.strip()]
Value Validation
Add validation logic in the Config class constructor:
class Config(object):
def __init__(self, ...):
# ... existing code ...
self.new_param = self._get("new_param")
# Validation
if self.new_param and not self._validate_new_param():
raise ValueError("Invalid new_param value")
def _validate_new_param(self):
"""Validate new parameter value"""
return True # Implement validation logic
Configuration Loading Flow
The complete configuration loading process:
def load_all_config():
# 1. Load command line arguments
cli_config = cli.load_config(...)
# 2. Load JSON configuration file
json_config = file.load_config(cli_config.get("config"))
# 3. Load environment variables
env_config = env.load_config()
# 4. Create Config instance
config = Config(cli_config, json_config, env_config)
return config
Testing Configuration System
Unit Testing
Create comprehensive tests for each configuration module:
# tests/test_config_new_param.py
import unittest
from ddns.config.config import Config
class TestConfigNewParam(unittest.TestCase):
def test_new_param_from_cli(self):
cli_config = {"new_param": "cli_value"}
config = Config(cli_config=cli_config)
self.assertEqual(config.new_param, "cli_value")
def test_new_param_priority(self):
cli_config = {"new_param": "cli_value"}
json_config = {"new_param": "json_value"}
env_config = {"new_param": "env_value"}
config = Config(cli_config, json_config, env_config)
self.assertEqual(config.new_param, "cli_value") # CLI has highest priority
Integration Testing
Test the complete configuration loading process:
def test_full_config_loading():
# Test with actual configuration files and environment variables
import os
os.environ["DDNS_NEW_PARAM"] = "test_value"
config = load_all_config()
assert config.new_param == "test_value"
Best Practices
1. Backward Compatibility
When adding new parameters, ensure backward compatibility:
# Support both old and new parameter names
self.new_param = self._get("new_param") or self._get("old_param")
2. Default Values
Provide sensible defaults for all parameters:
self.new_param = self._get("new_param", "default_value")
3. Type Safety
Use appropriate type conversion and validation:
# Convert string to integer with validation
try:
self.timeout = int(self._get("timeout", 30))
except ValueError:
raise ValueError("Invalid timeout value")
4. Documentation
Always update documentation when adding new parameters:
- Add parameter to all relevant documentation files
- Include usage examples
- Document default values and valid ranges
Configuration Schema Validation
The DDNS configuration system uses JSON Schema for validation:
Schema Structure
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"dns": {
"type": "string",
"enum": ["dnspod", "cloudflare", "alidns", ...]
}
},
"required": ["dns"]
}
Adding Schema Validation
Add validation for new parameters:
{
"properties": {
"new_param": {
"type": "string",
"pattern": "^[a-zA-Z0-9_-]+$",
"minLength": 1,
"maxLength": 100,
"description": "New parameter description"
}
}
}
Error Handling
Configuration Errors
Implement proper error handling for configuration issues:
class ConfigError(Exception):
"""Configuration-related errors"""
pass
class Config(object):
def __init__(self, ...):
try:
self._validate_config()
except Exception as e:
raise ConfigError("Configuration validation failed: {}".format(e))
def _validate_config(self):
"""Validate complete configuration"""
if not self.dns:
raise ValueError("DNS provider is required")
User-Friendly Messages
Provide clear error messages for common configuration mistakes:
def _validate_dns_provider(self):
valid_providers = ["dnspod", "cloudflare", "alidns", ...]
if self.dns not in valid_providers:
raise ValueError(
"Invalid DNS provider '{}'. Valid options: {}".format(
self.dns, ", ".join(valid_providers)
)
)
Performance Considerations
Lazy Loading
Implement lazy loading for expensive configuration operations:
class Config(object):
def __init__(self, ...):
self._domains_cache = None
@property
def domains(self):
if self._domains_cache is None:
self._domains_cache = self._parse_domains()
return self._domains_cache
Configuration Caching
Cache parsed configuration to avoid repeated processing:
import functools
@functools.lru_cache(maxsize=1)
def load_json_config(config_file):
"""Load and cache JSON configuration"""
return json.load(open(config_file))
Debugging Configuration
Debug Output
Add debug output for configuration troubleshooting:
def debug_config(self):
"""Print configuration debug information"""
print("Configuration Sources:")
print(" CLI: {}".format(self._cli_config))
print(" JSON: {}".format(self._json_config))
print(" ENV: {}".format(self._env_config))
print("Final Configuration:")
for attr in dir(self):
if not attr.startswith("_"):
print(" {}: {}".format(attr, getattr(self, attr)))
Configuration Validation
Add validation checks that can be enabled in debug mode:
def validate_all(self):
"""Comprehensive configuration validation"""
errors = []
if not self.dns:
errors.append("DNS provider not specified")
if not self.token:
errors.append("Authentication token not provided")
if errors:
raise ConfigError("Configuration errors: {}".format("; ".join(errors)))
Summary
The DDNS configuration system is designed to be:
- Flexible: Support multiple configuration sources
- Extensible: Easy to add new parameters
- Robust: Comprehensive validation and error handling
- User-friendly: Clear documentation and error messages
When extending the configuration system, always follow these principles and update all relevant documentation and tests.