Initial commit: Tencent DNSPod DNS deployment skill
- Support for single record deployment - Batch deployment from JSON config - Service quick deployment (Web/API/CDN) - .env file support for secure credentials - Complete documentation
This commit is contained in:
5
.env.example
Normal file
5
.env.example
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# 腾讯云DNSPod API密钥配置
|
||||||
|
# 获取方式: https://console.cloud.tencent.com/cam/capi
|
||||||
|
|
||||||
|
TENCENT_SECRET_ID=你的SecretId
|
||||||
|
TENCENT_SECRET_KEY=你的SecretKey
|
||||||
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
|
||||||
|
# 虚拟环境
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# 敏感信息
|
||||||
|
.env
|
||||||
|
*.key
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# 临时文件
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
200
ENV_SETUP.md
Normal file
200
ENV_SETUP.md
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# 环境变量配置说明
|
||||||
|
|
||||||
|
## .env 文件(推荐方式)
|
||||||
|
|
||||||
|
`.env` 文件用于存储敏感配置信息,如API密钥。该文件**不会被提交到Git**(已添加到 `.gitignore`)。
|
||||||
|
|
||||||
|
### 配置步骤
|
||||||
|
|
||||||
|
1. **复制示例配置**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **编辑 .env 文件**
|
||||||
|
```bash
|
||||||
|
# 使用你喜欢的编辑器
|
||||||
|
vim .env
|
||||||
|
# 或
|
||||||
|
nano .env
|
||||||
|
# 或
|
||||||
|
code .env
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **填入你的腾讯云API密钥**
|
||||||
|
```bash
|
||||||
|
TENCENT_SECRET_ID=你的SecretId
|
||||||
|
TENCENT_SECRET_KEY=你的SecretKey
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **保存文件**
|
||||||
|
|
||||||
|
### 获取API密钥
|
||||||
|
|
||||||
|
访问腾讯云控制台: https://console.cloud.tencent.com/cam/capi
|
||||||
|
|
||||||
|
- 点击「新建密钥」或查看现有密钥
|
||||||
|
- 复制 `SecretId` 和 `SecretKey`
|
||||||
|
- ⚠️ **重要:** SecretKey只在创建时显示一次,请妥善保存!
|
||||||
|
|
||||||
|
## 环境变量方式
|
||||||
|
|
||||||
|
如果不使用 `.env` 文件,可以直接设置系统环境变量。
|
||||||
|
|
||||||
|
### Linux/Mac
|
||||||
|
|
||||||
|
**临时设置(当前会话有效):**
|
||||||
|
```bash
|
||||||
|
export TENCENT_SECRET_ID="你的SecretId"
|
||||||
|
export TENCENT_SECRET_KEY="你的SecretKey"
|
||||||
|
```
|
||||||
|
|
||||||
|
**永久设置(添加到 ~/.bashrc 或 ~/.zshrc):**
|
||||||
|
```bash
|
||||||
|
echo 'export TENCENT_SECRET_ID="你的SecretId"' >> ~/.bashrc
|
||||||
|
echo 'export TENCENT_SECRET_KEY="你的SecretKey"' >> ~/.bashrc
|
||||||
|
source ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
**PowerShell临时设置:**
|
||||||
|
```powershell
|
||||||
|
$env:TENCENT_SECRET_ID="你的SecretId"
|
||||||
|
$env:TENCENT_SECRET_KEY="你的SecretKey"
|
||||||
|
```
|
||||||
|
|
||||||
|
**PowerShell永久设置:**
|
||||||
|
```powershell
|
||||||
|
[System.Environment]::SetEnvironmentVariable('TENCENT_SECRET_ID', '你的SecretId', 'User')
|
||||||
|
[System.Environment]::SetEnvironmentVariable('TENCENT_SECRET_KEY', '你的SecretKey', 'User')
|
||||||
|
```
|
||||||
|
|
||||||
|
**CMD临时设置:**
|
||||||
|
```cmd
|
||||||
|
set TENCENT_SECRET_ID=你的SecretId
|
||||||
|
set TENCENT_SECRET_KEY=你的SecretKey
|
||||||
|
```
|
||||||
|
|
||||||
|
## 验证配置
|
||||||
|
|
||||||
|
### 方式1: 查看 .env 文件
|
||||||
|
```bash
|
||||||
|
cat .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式2: 查看环境变量
|
||||||
|
```bash
|
||||||
|
# Linux/Mac
|
||||||
|
echo $TENCENT_SECRET_ID
|
||||||
|
|
||||||
|
# Windows PowerShell
|
||||||
|
echo $env:TENCENT_SECRET_ID
|
||||||
|
|
||||||
|
# Windows CMD
|
||||||
|
echo %TENCENT_SECRET_ID%
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式3: 测试连接
|
||||||
|
```bash
|
||||||
|
python scripts/list_records.py --domain example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
如果成功,将显示域名记录列表(可能为空)。
|
||||||
|
|
||||||
|
## 安全建议
|
||||||
|
|
||||||
|
### ✅ 推荐做法
|
||||||
|
|
||||||
|
1. **使用 .env 文件** - 方便管理,不会被Git跟踪
|
||||||
|
2. **使用 .env.example** - 提供配置模板,不含真实密钥
|
||||||
|
3. **定期轮换密钥** - 定期更换API密钥提高安全性
|
||||||
|
4. **使用子账号** - 创建独立的子账号,只授予必要权限
|
||||||
|
5. **设置IP白名单** - 在腾讯云CAM中限制API调用来源IP
|
||||||
|
|
||||||
|
### ❌ 避免做法
|
||||||
|
|
||||||
|
1. ❌ 不要将密钥硬编码在代码中
|
||||||
|
2. ❌ 不要在Git仓库中提交 .env 文件
|
||||||
|
3. ❌ 不要在生产环境使用默认密钥
|
||||||
|
4. ❌ 不要在公开场合分享密钥
|
||||||
|
5. ❌ 不要使用弱密钥或重复使用密钥
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q1: .env 文件不生效?
|
||||||
|
|
||||||
|
**原因:** 可能是文件权限问题或路径错误。
|
||||||
|
|
||||||
|
**解决:**
|
||||||
|
```bash
|
||||||
|
# 确认文件存在
|
||||||
|
ls -la .env
|
||||||
|
|
||||||
|
# 确认文件内容
|
||||||
|
cat .env
|
||||||
|
|
||||||
|
# 确认文件格式(无BOM,Unix换行符)
|
||||||
|
file .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q2: 还是提示找不到密钥?
|
||||||
|
|
||||||
|
**解决:** 检查 `.env` 文件是否在项目根目录:
|
||||||
|
```bash
|
||||||
|
pwd # 应该在 tencent-dnspod 目录
|
||||||
|
ls .env # 应该能看到 .env 文件
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q3: Git提交时意外包含了 .env?
|
||||||
|
|
||||||
|
**解决:**
|
||||||
|
```bash
|
||||||
|
# 1. 从Git中移除(但保留本地文件)
|
||||||
|
git rm --cached .env
|
||||||
|
|
||||||
|
# 2. 确认 .gitignore 包含 .env
|
||||||
|
echo ".env" >> .gitignore
|
||||||
|
|
||||||
|
# 3. 提交修改
|
||||||
|
git add .gitignore
|
||||||
|
git commit -m "Remove .env from tracking"
|
||||||
|
|
||||||
|
# 4. 更换已泄露的密钥!
|
||||||
|
# 访问: https://console.cloud.tencent.com/cam/capi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q4: 多个项目需要不同的密钥?
|
||||||
|
|
||||||
|
**解决:** 每个项目使用独立的 .env 文件:
|
||||||
|
```bash
|
||||||
|
# 项目A
|
||||||
|
cd /path/to/project-a
|
||||||
|
echo "TENCENT_SECRET_ID=项目A的ID" > .env
|
||||||
|
|
||||||
|
# 项目B
|
||||||
|
cd /path/to/project-b
|
||||||
|
echo "TENCENT_SECRET_ID=项目B的ID" > .env
|
||||||
|
```
|
||||||
|
|
||||||
|
## 权限管理建议
|
||||||
|
|
||||||
|
### 创建专用子账号
|
||||||
|
|
||||||
|
1. 访问: https://console.cloud.tencent.com/cam
|
||||||
|
2. 创建子账号,只授予DNSPod权限
|
||||||
|
3. 为子账号创建API密钥
|
||||||
|
4. 使用子账号密钥而非主账号密钥
|
||||||
|
|
||||||
|
### 最小权限原则
|
||||||
|
|
||||||
|
只授予必要的权限:
|
||||||
|
- DNSPod只读权限(查询记录)
|
||||||
|
- DNSPod读写权限(管理记录)
|
||||||
|
- 避免授予所有产品的访问权限
|
||||||
|
|
||||||
|
## 参考文档
|
||||||
|
|
||||||
|
- **腾讯云访问管理(CAM):** https://cloud.tencent.com/document/product/598
|
||||||
|
- **API密钥管理:** https://console.cloud.tencent.com/cam/capi
|
||||||
|
- **子账号权限:** https://console.cloud.tencent.com/cam/user
|
||||||
339
INSTALL.md
Normal file
339
INSTALL.md
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
# DNSPod Skill 安装指南
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
本Skill已针对**域名快速部署**场景优化,提供以下核心功能:
|
||||||
|
|
||||||
|
✅ **单条记录快速部署** - 秒级添加/更新DNS记录
|
||||||
|
✅ **批量部署** - 从JSON配置文件一键部署多条记录
|
||||||
|
✅ **服务快速部署** - 一键配置Web/API/CDN服务
|
||||||
|
✅ **自动化友好** - 支持DevOps CI/CD集成
|
||||||
|
|
||||||
|
## 核心脚本
|
||||||
|
|
||||||
|
### 1. `deploy_record.py` - 单条记录部署
|
||||||
|
```bash
|
||||||
|
# 添加A记录
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.4
|
||||||
|
|
||||||
|
# 强制更新
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.5 \
|
||||||
|
--force
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. `batch_deploy.py` - 批量部署
|
||||||
|
```bash
|
||||||
|
# 从配置文件批量部署
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config examples/dns-config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. `deploy_service.py` - 服务快速部署
|
||||||
|
```bash
|
||||||
|
# 部署Web服务(@ + www)
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service web \
|
||||||
|
--ip 1.2.3.4
|
||||||
|
|
||||||
|
# 部署API服务
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service api \
|
||||||
|
--ip 1.2.3.5
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. `list_records.py` - 查询记录
|
||||||
|
```bash
|
||||||
|
python scripts/list_records.py --domain example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. `delete_record.py` - 删除记录
|
||||||
|
```bash
|
||||||
|
python scripts/delete_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A
|
||||||
|
```
|
||||||
|
|
||||||
|
## 安装步骤
|
||||||
|
|
||||||
|
### 步骤1: 获取腾讯云API密钥
|
||||||
|
|
||||||
|
1. 访问: https://console.cloud.tencent.com/cam/capi
|
||||||
|
2. 创建或查看密钥(包含 `SecretId` 和 `SecretKey`)
|
||||||
|
3. ⚠️ **重要:** SecretKey只在创建时显示,请立即保存!
|
||||||
|
|
||||||
|
### 步骤2: 配置API密钥
|
||||||
|
|
||||||
|
有两种方式配置API密钥:
|
||||||
|
|
||||||
|
#### 方式1: 使用 .env 文件(推荐,更安全)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 复制示例配置
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# 2. 编辑 .env 文件,填入你的密钥
|
||||||
|
# TENCENT_SECRET_ID=你的SecretId
|
||||||
|
# TENCENT_SECRET_KEY=你的SecretKey
|
||||||
|
|
||||||
|
# 3. 确保 .env 文件不会被提交到Git(已添加到 .gitignore)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方式2: 设置环境变量
|
||||||
|
|
||||||
|
**Linux/Mac (添加到 ~/.bashrc 或 ~/.zshrc):**
|
||||||
|
```bash
|
||||||
|
export TENCENT_SECRET_ID="你的SecretId"
|
||||||
|
export TENCENT_SECRET_KEY="你的SecretKey"
|
||||||
|
source ~/.bashrc # 重新加载
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows PowerShell:**
|
||||||
|
```powershell
|
||||||
|
[System.Environment]::SetEnvironmentVariable('TENCENT_SECRET_ID', '你的SecretId', 'User')
|
||||||
|
[System.Environment]::SetEnvironmentVariable('TENCENT_SECRET_KEY', '你的SecretKey', 'User')
|
||||||
|
```
|
||||||
|
|
||||||
|
**验证配置:**
|
||||||
|
```bash
|
||||||
|
# 方式1: 查看 .env 文件
|
||||||
|
cat .env
|
||||||
|
|
||||||
|
# 方式2: 查看环境变量
|
||||||
|
# Linux/Mac
|
||||||
|
echo $TENCENT_SECRET_ID
|
||||||
|
|
||||||
|
# Windows PowerShell
|
||||||
|
echo $env:TENCENT_SECRET_ID
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤3: 安装Python依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tencent-dnspod
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
依赖项:
|
||||||
|
- `requests>=2.28.0` (HTTP请求库)
|
||||||
|
|
||||||
|
### 步骤4: 测试连接
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/list_records.py --domain example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
如果成功,将显示域名下的DNS记录列表(可能为空)。
|
||||||
|
|
||||||
|
## 典型使用场景
|
||||||
|
|
||||||
|
### 场景1: 新服务快速上线
|
||||||
|
|
||||||
|
**需求:** 将新Web服务部署到 1.2.3.4
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 一键部署主域名 + www
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service web \
|
||||||
|
--ip 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
|
**结果:**
|
||||||
|
- ✅ example.com → 1.2.3.4
|
||||||
|
- ✅ www.example.com → 1.2.3.4
|
||||||
|
|
||||||
|
### 场景2: 多环境部署
|
||||||
|
|
||||||
|
**配置文件:** `dns-config.json`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{"subdomain": "www", "type": "A", "value": "1.2.3.4", "line": "默认", "remark": "生产"},
|
||||||
|
{"subdomain": "dev", "type": "A", "value": "1.2.3.5", "line": "默认", "remark": "开发"},
|
||||||
|
{"subdomain": "test", "type": "A", "value": "1.2.3.6", "line": "默认", "remark": "测试"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**批量部署:**
|
||||||
|
```bash
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config dns-config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景3: CDN加速配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 添加CNAME记录指向CDN
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain cdn \
|
||||||
|
--type CNAME \
|
||||||
|
--value cdn.example.com.cdn.dnsv1.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景4: 智能DNS(电信/联通线路)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 电信用户访问1.2.3.4
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.4 \
|
||||||
|
--line "电信"
|
||||||
|
|
||||||
|
# 联通用户访问5.6.7.8
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 5.6.7.8 \
|
||||||
|
--line "联通"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景5: CI/CD集成
|
||||||
|
|
||||||
|
**示例: Jenkins/GitLab CI**
|
||||||
|
```bash
|
||||||
|
# 部署时自动更新DNS
|
||||||
|
pip install -r tencent-dnspod/requirements.txt
|
||||||
|
|
||||||
|
# 部署新版本
|
||||||
|
docker push registry.example.com/myapp:v1.2.3
|
||||||
|
|
||||||
|
# 更新DNS
|
||||||
|
python tencent-dnspod/scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain app \
|
||||||
|
--type A \
|
||||||
|
--value $(kubectl get svc myapp -o jsonpath='{.status.loadBalancer.ingress[0].ip}') \
|
||||||
|
--force
|
||||||
|
```
|
||||||
|
|
||||||
|
## 高级功能
|
||||||
|
|
||||||
|
### 泛域名解析
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 部署Web服务时添加泛域名
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service web \
|
||||||
|
--ip 1.2.3.4 \
|
||||||
|
--wildcard
|
||||||
|
```
|
||||||
|
|
||||||
|
**结果:**
|
||||||
|
- ✅ example.com → 1.2.3.4
|
||||||
|
- ✅ www.example.com → 1.2.3.4
|
||||||
|
- ✅ *.example.com → 1.2.3.4
|
||||||
|
|
||||||
|
### TTL设置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 测试环境使用较短TTL(快速生效)
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain test \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.10 \
|
||||||
|
--ttl 60
|
||||||
|
```
|
||||||
|
|
||||||
|
### 记录备注
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 添加备注方便管理
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain api \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.5 \
|
||||||
|
--remark "后端API服务"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q1: 认证失败怎么办?
|
||||||
|
|
||||||
|
**错误:** `AuthFailure`
|
||||||
|
|
||||||
|
**解决:**
|
||||||
|
1. 检查环境变量是否正确设置
|
||||||
|
2. 确认SecretId和SecretKey匹配
|
||||||
|
3. 检查系统时间是否准确
|
||||||
|
|
||||||
|
### Q2: 域名不存在?
|
||||||
|
|
||||||
|
**错误:** `ResourceNotFound.Domain`
|
||||||
|
|
||||||
|
**解决:** 使用 `--create-domain` 参数自动创建:
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.4 \
|
||||||
|
--create-domain
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q3: 记录已存在?
|
||||||
|
|
||||||
|
**错误:** `RecordAlreadyExists`
|
||||||
|
|
||||||
|
**解决:** 使用 `--force` 参数强制更新:
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.5 \
|
||||||
|
--force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q4: API频率限制?
|
||||||
|
|
||||||
|
**错误:** `RequestLimitExceeded`
|
||||||
|
|
||||||
|
**解决:** 批量部署时增加延迟:
|
||||||
|
```bash
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config dns-config.json \
|
||||||
|
--delay 1.0 # 改为1秒延迟
|
||||||
|
```
|
||||||
|
|
||||||
|
## 文档索引
|
||||||
|
|
||||||
|
- **API认证:** [references/api-auth.md](references/api-auth.md)
|
||||||
|
- **错误处理:** [references/common-errors.md](references/common-errors.md)
|
||||||
|
- **完整文档:** [SKILL.md](SKILL.md)
|
||||||
|
|
||||||
|
## 技术支持
|
||||||
|
|
||||||
|
- **DNSPod文档:** https://cloud.tencent.com/document/product/1427/56152
|
||||||
|
- **API参考:** https://cloud.tencent.com/document/api/1427/56194
|
||||||
|
- **控制台:** https://console.dnspod.cn
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
### v1.0.0 (2026-03-01)
|
||||||
|
- ✅ 单条记录部署
|
||||||
|
- ✅ 批量部署
|
||||||
|
- ✅ 服务快速部署
|
||||||
|
- ✅ 记录查询和删除
|
||||||
|
- ✅ 完整错误处理
|
||||||
258
README.md
Normal file
258
README.md
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
# 腾讯云DNSPod域名快速部署 Skill
|
||||||
|
|
||||||
|
这是一个用于快速部署和自动化管理腾讯云DNSPod域名解析的OpenClaw Skill。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
✅ **单条记录快速部署** - 添加/更新A、CNAME、MX等记录
|
||||||
|
✅ **批量部署** - 从JSON配置文件批量创建记录
|
||||||
|
✅ **服务快速部署** - 一键部署Web、API、CDN等服务
|
||||||
|
✅ **记录查询** - 查看域名下的所有解析记录
|
||||||
|
✅ **记录删除** - 删除不需要的DNS记录
|
||||||
|
✅ **自动域名创建** - 部署时自动创建不存在的域名
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
### 1. 安装依赖
|
||||||
|
```bash
|
||||||
|
cd tencent-dnspod
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置认证密钥
|
||||||
|
|
||||||
|
访问腾讯云控制台获取API密钥:
|
||||||
|
https://console.cloud.tencent.com/cam/capi
|
||||||
|
|
||||||
|
有两种配置方式:
|
||||||
|
|
||||||
|
**方式1: 使用 .env 文件(推荐)**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# 编辑 .env 文件,填入你的密钥
|
||||||
|
```
|
||||||
|
|
||||||
|
**方式2: 设置环境变量**
|
||||||
|
```bash
|
||||||
|
export TENCENT_SECRET_ID="你的SecretId"
|
||||||
|
export TENCENT_SECRET_KEY="你的SecretKey"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 验证安装
|
||||||
|
```bash
|
||||||
|
python scripts/list_records.py --domain example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速使用
|
||||||
|
|
||||||
|
### 场景1: 部署Web服务
|
||||||
|
|
||||||
|
一键部署主域名和www子域名:
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service web \
|
||||||
|
--ip 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
|
带泛域名解析:
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service web \
|
||||||
|
--ip 1.2.3.4 \
|
||||||
|
--wildcard
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景2: 部署API服务
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service api \
|
||||||
|
--ip 1.2.3.5 \
|
||||||
|
--subdomain api
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景3: 批量部署
|
||||||
|
|
||||||
|
从配置文件批量部署:
|
||||||
|
```bash
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config examples/dns-config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景4: 单条记录管理
|
||||||
|
|
||||||
|
添加A记录:
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
|
添加CNAME记录(CDN):
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain cdn \
|
||||||
|
--type CNAME \
|
||||||
|
--value cdn.example.com.cdn.dnsv1.com
|
||||||
|
```
|
||||||
|
|
||||||
|
强制更新现有记录:
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.5 \
|
||||||
|
--force
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景5: 查询和删除
|
||||||
|
|
||||||
|
查询所有记录:
|
||||||
|
```bash
|
||||||
|
python scripts/list_records.py --domain example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
删除记录:
|
||||||
|
```bash
|
||||||
|
python scripts/delete_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A
|
||||||
|
```
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
tencent-dnspod/
|
||||||
|
├── SKILL.md # Skill说明文档
|
||||||
|
├── README.md # 本文件
|
||||||
|
├── requirements.txt # Python依赖
|
||||||
|
├── scripts/ # 脚本目录
|
||||||
|
│ ├── deploy_record.py # 单条记录部署
|
||||||
|
│ ├── batch_deploy.py # 批量部署
|
||||||
|
│ ├── deploy_service.py # 服务快速部署
|
||||||
|
│ ├── list_records.py # 记录查询
|
||||||
|
│ └── delete_record.py # 记录删除
|
||||||
|
├── references/ # 参考文档
|
||||||
|
│ ├── api-auth.md # API认证说明
|
||||||
|
│ └── common-errors.md # 常见错误处理
|
||||||
|
└── examples/ # 示例配置
|
||||||
|
└── dns-config.json # 批量部署配置示例
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置文件格式
|
||||||
|
|
||||||
|
批量部署配置文件(JSON格式):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"subdomain": "@",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认",
|
||||||
|
"ttl": 600,
|
||||||
|
"remark": "主域名"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "www",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认",
|
||||||
|
"remark": "Web服务"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "api",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.5",
|
||||||
|
"line": "电信",
|
||||||
|
"remark": "API服务"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "cdn",
|
||||||
|
"type": "CNAME",
|
||||||
|
"value": "cdn.example.com.cdn.dnsv1.com",
|
||||||
|
"line": "默认",
|
||||||
|
"remark": "CDN加速"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 支持的记录类型
|
||||||
|
|
||||||
|
| 类型 | 说明 | 示例值 |
|
||||||
|
|------|------|--------|
|
||||||
|
| A | IPv4地址 | 1.2.3.4 |
|
||||||
|
| AAAA | IPv6地址 | 2001:db8::1 |
|
||||||
|
| CNAME | 别名 | cdn.example.com |
|
||||||
|
| MX | 邮件服务器 | mx.example.com |
|
||||||
|
| TXT | 文本记录 | "v=spf1 include:_spf.example.com ~all" |
|
||||||
|
| NS | 域名服务器 | ns1.example.com |
|
||||||
|
|
||||||
|
## 常用线路
|
||||||
|
|
||||||
|
- `默认` - 默认线路
|
||||||
|
- `电信` - 电信用户
|
||||||
|
- `联通` - 联通用户
|
||||||
|
- `移动` - 移动用户
|
||||||
|
- `境外` - 海外用户
|
||||||
|
- `搜索引擎` - 爬虫线路
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
1. **部署前测试** - 先在测试域名验证配置
|
||||||
|
2. **设置合理TTL** - 生产环境600s,测试环境60s
|
||||||
|
3. **使用批量部署** - 多条记录用配置文件管理
|
||||||
|
4. **添加记录备注** - 方便后续维护
|
||||||
|
5. **分环境管理** - 使用不同子域名(dev/stage/prod)
|
||||||
|
6. **注意API限频** - 批量操作时控制请求频率
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 1. 认证失败
|
||||||
|
```
|
||||||
|
错误: AuthFailure
|
||||||
|
解决: 检查环境变量 TENCENT_SECRET_ID 和 TENCENT_SECRET_KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 域名不存在
|
||||||
|
```
|
||||||
|
错误: ResourceNotFound.Domain
|
||||||
|
解决: 使用 --create-domain 参数自动创建域名
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 记录已存在
|
||||||
|
```
|
||||||
|
错误: RecordAlreadyExists
|
||||||
|
解决: 使用 --force 参数强制更新
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. API频率限制
|
||||||
|
```
|
||||||
|
错误: RequestLimitExceeded
|
||||||
|
解决: 批量操作时增加 --delay 参数(默认0.5秒)
|
||||||
|
```
|
||||||
|
|
||||||
|
详细错误处理见: [references/common-errors.md](references/common-errors.md)
|
||||||
|
|
||||||
|
## 技术支持
|
||||||
|
|
||||||
|
- **DNSPod API文档:** https://cloud.tencent.com/document/product/1427/56152
|
||||||
|
- **腾讯云SDK:** https://cloud.tencent.com/document/sdk
|
||||||
|
- **DNSPod控制台:** https://console.dnspod.cn
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
## 贡献
|
||||||
|
|
||||||
|
欢迎提交Issue和Pull Request!
|
||||||
259
SKILL.md
Normal file
259
SKILL.md
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
---
|
||||||
|
name: tencent-dnspod
|
||||||
|
description: |
|
||||||
|
腾讯云DNSPod域名快速部署工具。用于自动化部署DNS记录、批量配置域名解析、快速上线服务。
|
||||||
|
当用户需要: (1) 快速添加DNS记录部署新服务, (2) 批量配置A/CNAME/MX等记录,
|
||||||
|
(3) 域名解析自动化管理, (4) DevOps域名部署流程时触发。
|
||||||
|
---
|
||||||
|
|
||||||
|
# 腾讯云DNSPod域名快速部署
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 配置认证
|
||||||
|
|
||||||
|
获取API密钥: https://console.cloud.tencent.com/cam/capi
|
||||||
|
|
||||||
|
**方式1: 使用 .env 文件(推荐,更安全):**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# 编辑 .env 文件,填入你的密钥
|
||||||
|
```
|
||||||
|
|
||||||
|
**方式2: 设置环境变量:**
|
||||||
|
```bash
|
||||||
|
export TENCENT_SECRET_ID="你的SecretId"
|
||||||
|
export TENCENT_SECRET_KEY="你的SecretKey"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 核心命令
|
||||||
|
|
||||||
|
**添加单条记录(最常用):**
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.4 \
|
||||||
|
--line "默认"
|
||||||
|
```
|
||||||
|
|
||||||
|
**批量部署(从配置文件):**
|
||||||
|
```bash
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config dns-config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
**快速配置服务(常用组合):**
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service web \
|
||||||
|
--ip 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
|
**删除记录:**
|
||||||
|
```bash
|
||||||
|
python scripts/delete_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain www
|
||||||
|
```
|
||||||
|
|
||||||
|
## 域名快速部署流程
|
||||||
|
|
||||||
|
### 场景1: 部署新Web服务
|
||||||
|
```bash
|
||||||
|
# 一键部署www和主域名
|
||||||
|
python scripts/deploy_service.py \
|
||||||
|
--domain example.com \
|
||||||
|
--service web \
|
||||||
|
--ip 1.2.3.4
|
||||||
|
|
||||||
|
# 自动创建:
|
||||||
|
# - example.com (A记录)
|
||||||
|
# - www.example.com (A记录)
|
||||||
|
# - *.example.com (泛域名A记录,可选)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景2: 部署API服务
|
||||||
|
```bash
|
||||||
|
# 部署api子域名
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain api \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景3: 配置邮件服务
|
||||||
|
```bash
|
||||||
|
# 一键配置MX记录
|
||||||
|
python scripts/deploy_mx.py \
|
||||||
|
--domain example.com \
|
||||||
|
--mx-server mx.example.com \
|
||||||
|
--priority 10
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景4: CDN加速配置
|
||||||
|
```bash
|
||||||
|
# 添加CNAME指向CDN
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--subdomain cdn \
|
||||||
|
--type CNAME \
|
||||||
|
--value cdn.example.com.cdn.dnsv1.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景5: 批量部署多个环境
|
||||||
|
```bash
|
||||||
|
# 从配置文件批量创建
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config deployments/dev.json
|
||||||
|
|
||||||
|
# 配置文件示例见下文
|
||||||
|
```
|
||||||
|
|
||||||
|
## 记录类型说明
|
||||||
|
|
||||||
|
| 类型 | 用途 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| A | 指向IPv4地址 | www → 1.2.3.4 |
|
||||||
|
| CNAME | 指向域名别名 | www → cdn.example.com |
|
||||||
|
| MX | 邮件服务器 | @ → mx.example.com |
|
||||||
|
| TXT | 文本记录(验证/SPF) | @ → "v=spf1 include:_spf.example.com ~all" |
|
||||||
|
| AAAA | 指向IPv6地址 | www → 2001:db8::1 |
|
||||||
|
|
||||||
|
## 批量部署配置文件格式
|
||||||
|
|
||||||
|
`dns-config.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"subdomain": "@",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "www",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "api",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.5",
|
||||||
|
"line": "电信"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "cdn",
|
||||||
|
"type": "CNAME",
|
||||||
|
"value": "cdn.example.com.cdn.dnsv1.com",
|
||||||
|
"line": "默认"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
使用批量配置:
|
||||||
|
```bash
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config dns-config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 线路类型说明
|
||||||
|
|
||||||
|
常用线路值:
|
||||||
|
- `默认` - 默认线路
|
||||||
|
- `电信` - 电信用户
|
||||||
|
- `联通` - 联通用户
|
||||||
|
- `移动` - 移动用户
|
||||||
|
- `境外` - 海外用户
|
||||||
|
- `搜索引擎` - 爬虫线路
|
||||||
|
|
||||||
|
查看完整线路列表:
|
||||||
|
```bash
|
||||||
|
python scripts/list_lines.py --domain example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 1. 记录冲突
|
||||||
|
如果记录已存在,脚本会提示是否更新。使用 `--force` 强制更新。
|
||||||
|
|
||||||
|
### 2. 批量操作失败
|
||||||
|
批量操作会继续执行后续记录,最后汇总结果。检查输出中的 `[FAIL]` 标记。
|
||||||
|
|
||||||
|
### 3. API频率限制
|
||||||
|
默认限制: 20次/秒。大批量部署时会自动限速。
|
||||||
|
|
||||||
|
### 4. 域名未添加
|
||||||
|
如果域名未添加到DNSPod,使用 `--create-domain` 自动创建:
|
||||||
|
```bash
|
||||||
|
python scripts/deploy_record.py \
|
||||||
|
--domain example.com \
|
||||||
|
--create-domain \
|
||||||
|
--subdomain www \
|
||||||
|
--type A \
|
||||||
|
--value 1.2.3.4
|
||||||
|
```
|
||||||
|
|
||||||
|
## API错误处理
|
||||||
|
|
||||||
|
详细错误说明见 [common-errors.md](references/common-errors.md)
|
||||||
|
|
||||||
|
## 高级功能
|
||||||
|
|
||||||
|
### 创建快照(部署前备份)
|
||||||
|
```bash
|
||||||
|
python/scripts/snapshot.py \
|
||||||
|
--domain example.com \
|
||||||
|
--action create \
|
||||||
|
--name "部署前备份"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 回滚快照
|
||||||
|
```bash
|
||||||
|
python scripts/snapshot.py \
|
||||||
|
--domain example.com \
|
||||||
|
--action rollback \
|
||||||
|
--snapshot-id <snapshot-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 查看部署历史
|
||||||
|
```bash
|
||||||
|
python scripts/list_records.py \
|
||||||
|
--domain example.com \
|
||||||
|
--show-changes
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
1. **部署前备份** - 重大部署前先创建快照
|
||||||
|
2. **分环境管理** - 使用不同子域名(dev/stage/prod)
|
||||||
|
3. **TTL设置** - 生产环境600s,测试环境60s
|
||||||
|
4. **批量测试** - 先在测试域名验证配置,再批量部署
|
||||||
|
5. **记录备注** - 添加 `--remark` 标记记录用途
|
||||||
|
|
||||||
|
## 示例: 完整部署流程
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 部署前备份
|
||||||
|
python scripts/snapshot.py --domain example.com --action create --name "部署前"
|
||||||
|
|
||||||
|
# 2. 批量部署
|
||||||
|
python scripts/batch_deploy.py \
|
||||||
|
--domain example.com \
|
||||||
|
--config dns-config.json
|
||||||
|
|
||||||
|
# 3. 验证部署
|
||||||
|
python scripts/list_records.py --domain example.com
|
||||||
|
|
||||||
|
# 4. 测试解析
|
||||||
|
dig www.example.com
|
||||||
|
```
|
||||||
44
examples/dns-config.json
Normal file
44
examples/dns-config.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"subdomain": "@",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认",
|
||||||
|
"ttl": 600,
|
||||||
|
"remark": "主域名"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "www",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认",
|
||||||
|
"ttl": 600,
|
||||||
|
"remark": "Web服务"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "api",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.5",
|
||||||
|
"line": "默认",
|
||||||
|
"ttl": 600,
|
||||||
|
"remark": "API服务"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "cdn",
|
||||||
|
"type": "CNAME",
|
||||||
|
"value": "cdn.example.com.cdn.dnsv1.com",
|
||||||
|
"line": "默认",
|
||||||
|
"ttl": 600,
|
||||||
|
"remark": "CDN加速"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "test",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.10",
|
||||||
|
"line": "默认",
|
||||||
|
"ttl": 60,
|
||||||
|
"remark": "测试环境"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
180
references/api-auth.md
Normal file
180
references/api-auth.md
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# 腾讯云API认证说明
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
DNSPod API使用腾讯云统一的API v3签名算法,基于HMAC-SHA256进行请求签名认证。
|
||||||
|
|
||||||
|
## 获取密钥
|
||||||
|
|
||||||
|
### 1. 访问API密钥管理页面
|
||||||
|
https://console.cloud.tencent.com/cam/capi
|
||||||
|
|
||||||
|
### 2. 创建密钥
|
||||||
|
- 点击「新建密钥」或「访问密钥」
|
||||||
|
- 系统生成 `SecretId` 和 `SecretKey`
|
||||||
|
|
||||||
|
### 3. 保存密钥
|
||||||
|
⚠️ **重要:** SecretKey只在创建时显示一次,请妥善保存!
|
||||||
|
|
||||||
|
### 4. 设置环境变量
|
||||||
|
|
||||||
|
**Linux/Mac (Bash/Zsh):**
|
||||||
|
```bash
|
||||||
|
# 添加到 ~/.bashrc 或 ~/.zshrc
|
||||||
|
export TENCENT_SECRET_ID="你的SecretId"
|
||||||
|
export TENCENT_SECRET_KEY="你的SecretKey"
|
||||||
|
|
||||||
|
# 重新加载配置
|
||||||
|
source ~/.bashrc # 或 source ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows (PowerShell):**
|
||||||
|
```powershell
|
||||||
|
# 添加到环境变量
|
||||||
|
[System.Environment]::SetEnvironmentVariable('TENCENT_SECRET_ID', '你的SecretId', 'User')
|
||||||
|
[System.Environment]::SetEnvironmentVariable('TENCENT_SECRET_KEY', '你的SecretKey', 'User')
|
||||||
|
|
||||||
|
# 临时设置(当前会话有效)
|
||||||
|
$env:TENCENT_SECRET_ID="你的SecretId"
|
||||||
|
$env:TENCENT_SECRET_KEY="你的SecretKey"
|
||||||
|
```
|
||||||
|
|
||||||
|
**验证环境变量:**
|
||||||
|
```bash
|
||||||
|
# Linux/Mac
|
||||||
|
echo $TENCENT_SECRET_ID
|
||||||
|
|
||||||
|
# Windows PowerShell
|
||||||
|
echo $env:TENCENT_SECRET_ID
|
||||||
|
```
|
||||||
|
|
||||||
|
## 签名算法详解
|
||||||
|
|
||||||
|
### 1. 构造规范请求串
|
||||||
|
|
||||||
|
**格式:**
|
||||||
|
```
|
||||||
|
HTTPRequestMethod + '\n' +
|
||||||
|
CanonicalURI + '\n' +
|
||||||
|
CanonicalQueryString + '\n' +
|
||||||
|
CanonicalHeaders + '\n' +
|
||||||
|
SignedHeaders + '\n' +
|
||||||
|
HexEncode(Hash(RequestPayload))
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例:**
|
||||||
|
```
|
||||||
|
POST
|
||||||
|
/
|
||||||
|
content-type:application/json
|
||||||
|
host:dnspod.tencentcloudapi.com
|
||||||
|
|
||||||
|
content-type;host
|
||||||
|
356f92b5d0373084a2bc07df8267b0ab
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 构造待签名字符串
|
||||||
|
|
||||||
|
**格式:**
|
||||||
|
```
|
||||||
|
Algorithm + '\n' +
|
||||||
|
RequestTimestamp + '\n' +
|
||||||
|
CredentialScope + '\n' +
|
||||||
|
HexEncode(Hash(CanonicalRequest))
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例:**
|
||||||
|
```
|
||||||
|
TC3-HMAC-SHA256
|
||||||
|
1666666666
|
||||||
|
2021-03-23/dnspod/tc3_request
|
||||||
|
5c9d88e6d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 计算签名
|
||||||
|
|
||||||
|
使用 HMAC-SHA256 算法分三次计算:
|
||||||
|
|
||||||
|
```python
|
||||||
|
secret_date = HMAC_SHA256("TC3" + SecretKey, Date)
|
||||||
|
secret_service = HMAC_SHA256(secret_date, Service)
|
||||||
|
secret_signing = HMAC_SHA256(secret_service, "tc3_request")
|
||||||
|
signature = HMAC_SHA256(secret_signing, StringToSign)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 构造Authorization头
|
||||||
|
|
||||||
|
**格式:**
|
||||||
|
```
|
||||||
|
Algorithm Credential={SecretId}/{CredentialScope}, SignedHeaders={SignedHeaders}, Signature={Signature}
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例:**
|
||||||
|
```
|
||||||
|
TC3-HMAC-SHA256 Credential=AKIDxxxxxxxx/2021-03-23/dnspod/tc3_request, SignedHeaders=content-type;host, Signature=5c9d88e6d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d4c4d
|
||||||
|
```
|
||||||
|
|
||||||
|
## 完整请求示例
|
||||||
|
|
||||||
|
### 请求头
|
||||||
|
```http
|
||||||
|
POST / HTTP/1.1
|
||||||
|
Host: dnspod.tencentcloudapi.com
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: TC3-HMAC-SHA256 Credential=AKIDxxxxxxxx/2021-03-23/dnspod/tc3_request, SignedHeaders=content-type;host, Signature=xxxxxxxx
|
||||||
|
X-TC-Action: DescribeRecordList
|
||||||
|
X-TC-Timestamp: 1666666666
|
||||||
|
X-TC-Version: 2021-03-23
|
||||||
|
X-TC-Region: ap-guangzhou
|
||||||
|
```
|
||||||
|
|
||||||
|
### 请求体
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Domain": "example.com"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 请求参数说明
|
||||||
|
|
||||||
|
| 参数 | 说明 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| X-TC-Action | 操作名称 | CreateRecord |
|
||||||
|
| X-TC-Version | API版本 | 2021-03-23 |
|
||||||
|
| X-TC-Timestamp | 时间戳(秒) | 1666666666 |
|
||||||
|
| X-TC-Region | 地域 | ap-guangzhou |
|
||||||
|
| Authorization | 签名信息 | 见上文 |
|
||||||
|
|
||||||
|
## 地域说明
|
||||||
|
|
||||||
|
DNSPod API支持的地域:
|
||||||
|
|
||||||
|
- **ap-guangzhou** (广州,推荐)
|
||||||
|
- **ap-shanghai** (上海)
|
||||||
|
- **ap-beijing** (北京)
|
||||||
|
- **ap-chengdu** (成都)
|
||||||
|
|
||||||
|
建议选择就近地域以降低延迟。
|
||||||
|
|
||||||
|
## 安全建议
|
||||||
|
|
||||||
|
### 1. 密钥安全
|
||||||
|
- ⚠️ 不要将密钥硬编码在代码中
|
||||||
|
- ⚠️ 不要在Git仓库中提交密钥
|
||||||
|
- ✓ 使用环境变量或配置文件
|
||||||
|
- ✓ 定期轮换密钥
|
||||||
|
|
||||||
|
### 2. 权限管理
|
||||||
|
- 为不同应用创建独立的子账号
|
||||||
|
- 只授予必要的权限(最小权限原则)
|
||||||
|
- 定期审计密钥使用情况
|
||||||
|
|
||||||
|
### 3. IP白名单
|
||||||
|
- 在腾讯云访问管理(CAM)中设置IP白名单
|
||||||
|
- 限制只有特定IP才能调用API
|
||||||
|
|
||||||
|
## 参考文档
|
||||||
|
|
||||||
|
- **API签名文档:** https://cloud.tencent.com/document/product/1427/56152
|
||||||
|
- **访问管理(CAM):** https://cloud.tencent.com/document/product/598
|
||||||
|
- **SDK示例:** https://cloud.tencent.com/document/sdk
|
||||||
192
references/common-errors.md
Normal file
192
references/common-errors.md
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
# DNSPod API常见错误处理
|
||||||
|
|
||||||
|
## 错误码说明
|
||||||
|
|
||||||
|
### 认证相关
|
||||||
|
|
||||||
|
#### AuthFailure
|
||||||
|
**错误:** 签名验证失败
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- SecretId或SecretKey错误
|
||||||
|
- 签名算法错误
|
||||||
|
- 请求时间戳偏差过大
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
1. 检查环境变量 `TENCENT_SECRET_ID` 和 `TENCENT_SECRET_KEY`
|
||||||
|
2. 确认密钥未过期且状态正常
|
||||||
|
3. 检查系统时间是否准确(误差不超过5分钟)
|
||||||
|
|
||||||
|
#### AuthFailure.SecretIdNotFound
|
||||||
|
**错误:** SecretId不存在
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- SecretId输入错误
|
||||||
|
- 密钥已被删除
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 访问 https://console.cloud.tencent.com/cam/capi 重新获取
|
||||||
|
|
||||||
|
### 域名相关
|
||||||
|
|
||||||
|
#### ResourceNotFound.Domain
|
||||||
|
**错误:** 域名不存在
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 域名未添加到DNSPod
|
||||||
|
- 域名名称输入错误
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 检查域名拼写
|
||||||
|
- 使用 `--create-domain` 自动创建域名
|
||||||
|
- 手动在DNSPod控制台添加域名
|
||||||
|
|
||||||
|
#### ResourceNotFound.DomainOffline
|
||||||
|
**错误:** 域名已停用
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 域名已被禁用
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 登录DNSPod控制台重新启用域名
|
||||||
|
|
||||||
|
### 记录相关
|
||||||
|
|
||||||
|
#### InvalidParameter.RecordAlreadyExists
|
||||||
|
**错误:** 记录已存在
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 相同的主机记录、类型、线路的记录已存在
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 使用 `--force` 参数强制更新
|
||||||
|
- 先删除现有记录再创建
|
||||||
|
|
||||||
|
#### InvalidParameter.RecordNotFound
|
||||||
|
**错误:** 记录不存在
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- RecordId错误
|
||||||
|
- 记录已被删除
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 使用 `list_records.py` 查询正确的记录ID
|
||||||
|
|
||||||
|
#### InvalidParameter.RecordValueInvalid
|
||||||
|
**错误:** 记录值格式错误
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- IP地址格式错误
|
||||||
|
- CNAME目标域名格式错误
|
||||||
|
- 记录值与类型不匹配
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- A记录值必须是IPv4地址(如: 1.2.3.4)
|
||||||
|
- CNAME记录值必须是域名(如: cdn.example.com)
|
||||||
|
- MX记录值格式: `mx.example.com` (优先级单独设置)
|
||||||
|
|
||||||
|
### 限频相关
|
||||||
|
|
||||||
|
#### RequestLimitExceeded
|
||||||
|
**错误:** 请求频率超限
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- API调用超过频率限制(默认: 20次/秒)
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 降低请求频率
|
||||||
|
- 批量操作时增加 `--delay` 参数
|
||||||
|
- 使用批量API代替循环调用
|
||||||
|
|
||||||
|
#### LimitExceeded.DomainRecord
|
||||||
|
**错误:** 域名记录数超限
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 该域名下的记录数超过套餐限制
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 删除不需要的记录
|
||||||
|
- 升级DNSPod套餐
|
||||||
|
|
||||||
|
### 参数相关
|
||||||
|
|
||||||
|
#### InvalidParameter
|
||||||
|
**错误:** 参数错误
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 必填参数缺失
|
||||||
|
- 参数格式错误
|
||||||
|
- 参数值超出范围
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 检查命令行参数拼写
|
||||||
|
- 确认参数值格式正确
|
||||||
|
- 查看API文档确认参数要求
|
||||||
|
|
||||||
|
#### MissingParameter
|
||||||
|
**错误:** 缺少必填参数
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 未提供必要的参数
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 使用 `--help` 查看必填参数
|
||||||
|
- 补充完整的参数
|
||||||
|
|
||||||
|
### 其他常见错误
|
||||||
|
|
||||||
|
#### UnknownParameter
|
||||||
|
**错误:** 未知参数
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 传递了不支持的参数
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 检查参数名称拼写
|
||||||
|
- 确认API版本支持该参数
|
||||||
|
|
||||||
|
#### UnsupportedOperation
|
||||||
|
**错误:** 不支持的操作
|
||||||
|
|
||||||
|
**原因:**
|
||||||
|
- 当前套餐不支持该功能
|
||||||
|
- 域名状态不允许该操作
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
- 升级DNSPod套餐
|
||||||
|
- 检查域名状态
|
||||||
|
|
||||||
|
## 调试技巧
|
||||||
|
|
||||||
|
### 1. 开启详细日志
|
||||||
|
在脚本中添加调试输出:
|
||||||
|
```python
|
||||||
|
import logging
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 打印API响应
|
||||||
|
查看完整的API错误信息:
|
||||||
|
```python
|
||||||
|
print(json.dumps(result, indent=2, ensure_ascii=False))
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 验证参数
|
||||||
|
在调用API前打印参数:
|
||||||
|
```python
|
||||||
|
print(f"参数: {params}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 测试连通性
|
||||||
|
检查网络连接:
|
||||||
|
```bash
|
||||||
|
ping dnspod.tencentcloudapi.com
|
||||||
|
curl -I https://dnspod.tencentcloudapi.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 获取帮助
|
||||||
|
|
||||||
|
- **API文档:** https://cloud.tencent.com/document/product/1427/56152
|
||||||
|
- **错误码参考:** https://cloud.tencent.com/document/product/1427/56190
|
||||||
|
- **工单系统:** https://console.cloud.tencent.com/workorder
|
||||||
|
- **技术支持:** 95716 (DNSPod技术热线)
|
||||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
requests>=2.28.0
|
||||||
|
python-dotenv>=1.0.0
|
||||||
171
scripts/batch_deploy.py
Executable file
171
scripts/batch_deploy.py
Executable file
@@ -0,0 +1,171 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
DNSPod批量部署脚本
|
||||||
|
从配置文件批量创建DNS记录
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from deploy_record import (
|
||||||
|
deploy_record,
|
||||||
|
check_domain_exists,
|
||||||
|
create_domain,
|
||||||
|
load_env
|
||||||
|
)
|
||||||
|
|
||||||
|
# 加载 .env
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
def load_config(config_file):
|
||||||
|
"""加载配置文件"""
|
||||||
|
if not Path(config_file).exists():
|
||||||
|
print(f"错误: 配置文件不存在: {config_file}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_file, 'r', encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
print(f"错误: 配置文件格式错误: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def batch_deploy(domain, config, create_domain_flag=False, delay=0.5):
|
||||||
|
"""批量部署DNS记录"""
|
||||||
|
records = config.get('records', [])
|
||||||
|
|
||||||
|
if not records:
|
||||||
|
print("错误: 配置文件中没有记录")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print(f"\n批量部署开始")
|
||||||
|
print(f"域名: {domain}")
|
||||||
|
print(f"记录数量: {len(records)}")
|
||||||
|
print(f"延迟: {delay}s\n")
|
||||||
|
|
||||||
|
# 检查域名是否存在
|
||||||
|
if not check_domain_exists(domain):
|
||||||
|
if create_domain_flag:
|
||||||
|
if not create_domain(domain):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(f"✗ 域名不存在: {domain}")
|
||||||
|
print(f"提示: 使用 --create-domain 自动创建域名")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 统计
|
||||||
|
success_count = 0
|
||||||
|
fail_count = 0
|
||||||
|
skip_count = 0
|
||||||
|
|
||||||
|
# 部署每条记录
|
||||||
|
for idx, record_config in enumerate(records, 1):
|
||||||
|
print(f"\n[{idx}/{len(records)}] 正在部署...")
|
||||||
|
|
||||||
|
subdomain = record_config.get('subdomain', '@')
|
||||||
|
record_type = record_config.get('type')
|
||||||
|
value = record_config.get('value')
|
||||||
|
line = record_config.get('line', '默认')
|
||||||
|
ttl = record_config.get('ttl', 600)
|
||||||
|
remark = record_config.get('remark', '')
|
||||||
|
|
||||||
|
if not record_type or not value:
|
||||||
|
print(f"✗ 跳过: 缺少必要参数 (type或value)")
|
||||||
|
skip_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 部署记录
|
||||||
|
success = deploy_record(
|
||||||
|
domain=domain,
|
||||||
|
subdomain=subdomain,
|
||||||
|
record_type=record_type,
|
||||||
|
value=value,
|
||||||
|
line=line,
|
||||||
|
ttl=ttl,
|
||||||
|
force=True, # 批量模式自动更新
|
||||||
|
create_domain_flag=False,
|
||||||
|
remark=remark
|
||||||
|
)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
success_count += 1
|
||||||
|
else:
|
||||||
|
fail_count += 1
|
||||||
|
|
||||||
|
# API限频延迟
|
||||||
|
if idx < len(records):
|
||||||
|
time.sleep(delay)
|
||||||
|
|
||||||
|
# 输出统计
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"批量部署完成")
|
||||||
|
print(f" 成功: {success_count}")
|
||||||
|
print(f" 失败: {fail_count}")
|
||||||
|
print(f" 跳过: {skip_count}")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
return fail_count == 0
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='DNSPod批量部署', formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog='''
|
||||||
|
配置文件格式 (JSON):
|
||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"subdomain": "@",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认",
|
||||||
|
"ttl": 600,
|
||||||
|
"remark": "主域名"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "www",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.4",
|
||||||
|
"line": "默认"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"subdomain": "api",
|
||||||
|
"type": "A",
|
||||||
|
"value": "1.2.3.5",
|
||||||
|
"line": "电信"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
示例:
|
||||||
|
%(prog)s --domain example.com --config dns-config.json
|
||||||
|
%(prog)s --domain example.com --config dns-config.json --create-domain
|
||||||
|
%(prog)s --domain example.com --config dns-config.json --delay 1.0
|
||||||
|
''')
|
||||||
|
|
||||||
|
parser.add_argument('--domain', required=True, help='域名(如: example.com)')
|
||||||
|
parser.add_argument('--config', required=True, help='配置文件路径(JSON格式)')
|
||||||
|
parser.add_argument('--create-domain', action='store_true', help='域名不存在时自动创建')
|
||||||
|
parser.add_argument('--delay', type=float, default=0.5, help='API调用间隔(秒, 默认: 0.5, 避免限频)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# 加载配置
|
||||||
|
config = load_config(args.config)
|
||||||
|
if not config:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# 批量部署
|
||||||
|
success = batch_deploy(
|
||||||
|
domain=args.domain,
|
||||||
|
config=config,
|
||||||
|
create_domain_flag=args.create_domain,
|
||||||
|
delay=args.delay
|
||||||
|
)
|
||||||
|
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
68
scripts/delete_record.py
Executable file
68
scripts/delete_record.py
Executable file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
DNS记录删除脚本
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from deploy_record import (
|
||||||
|
call_api,
|
||||||
|
find_record,
|
||||||
|
load_env
|
||||||
|
)
|
||||||
|
|
||||||
|
# 加载 .env
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
def delete_record(domain, subdomain, record_type):
|
||||||
|
"""删除DNS记录"""
|
||||||
|
print(f"\n删除DNS记录: {subdomain or '@'}.{domain} ({record_type})")
|
||||||
|
|
||||||
|
# 查找记录
|
||||||
|
record = find_record(domain, subdomain, record_type)
|
||||||
|
|
||||||
|
if not record:
|
||||||
|
print(f"✗ 记录不存在")
|
||||||
|
return False
|
||||||
|
|
||||||
|
record_id = record.get("RecordId")
|
||||||
|
current_value = record.get("Value")
|
||||||
|
|
||||||
|
print(f" 记录ID: {record_id}")
|
||||||
|
print(f" 当前值: {current_value}")
|
||||||
|
|
||||||
|
# 确认删除
|
||||||
|
response = input("\n确认删除? (y/N): ")
|
||||||
|
if response.lower() != 'y':
|
||||||
|
print(" 已取消")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 调用删除API
|
||||||
|
try:
|
||||||
|
params = {
|
||||||
|
"Domain": domain,
|
||||||
|
"RecordId": record_id
|
||||||
|
}
|
||||||
|
result = call_api("DeleteRecord", params)
|
||||||
|
print(f"✓ 记录删除成功")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ 记录删除失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='删除DNS记录')
|
||||||
|
|
||||||
|
parser.add_argument('--domain', required=True, help='域名(如: example.com)')
|
||||||
|
parser.add_argument('--subdomain', default='@', help='子域名(默认: @)')
|
||||||
|
parser.add_argument('--type', required=True, help='记录类型(A/CNAME/MX等)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
success = delete_record(args.domain, args.subdomain, args.type)
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
337
scripts/deploy_record.py
Executable file
337
scripts/deploy_record.py
Executable file
@@ -0,0 +1,337 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
DNSPod单条记录部署脚本
|
||||||
|
用于快速添加或更新DNS记录
|
||||||
|
支持 .env 文件配置敏感信息
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import hmac
|
||||||
|
import hashlib
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
from urllib.parse import urlencode, quote
|
||||||
|
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
except ImportError:
|
||||||
|
print("错误: 缺少 requests 库")
|
||||||
|
print("请运行: pip install -r requirements.txt")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# 加载 .env 文件
|
||||||
|
def load_env():
|
||||||
|
"""加载.env文件"""
|
||||||
|
env_file = Path(__file__).parent.parent / '.env'
|
||||||
|
if env_file.exists():
|
||||||
|
with open(env_file, 'r', encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith('#') and '=' in line:
|
||||||
|
key, value = line.split('=', 1)
|
||||||
|
os.environ[key.strip()] = value.strip()
|
||||||
|
|
||||||
|
# 加载 .env
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
# API配置
|
||||||
|
API_ENDPOINT = "dnspod.tencentcloudapi.com"
|
||||||
|
API_VERSION = "2021-03-23"
|
||||||
|
REGION = "ap-guangzhou"
|
||||||
|
|
||||||
|
def get_credentials():
|
||||||
|
"""从环境变量或.env文件获取腾讯云凭证"""
|
||||||
|
secret_id = os.getenv('TENCENT_SECRET_ID')
|
||||||
|
secret_key = os.getenv('TENCENT_SECRET_KEY')
|
||||||
|
|
||||||
|
if not secret_id or not secret_key:
|
||||||
|
print("错误: 未找到腾讯云API密钥")
|
||||||
|
print("\n请设置环境变量或创建 .env 文件:")
|
||||||
|
print(" 方式1: 设置环境变量")
|
||||||
|
print(" export TENCENT_SECRET_ID=\"你的SecretId\"")
|
||||||
|
print(" export TENCENT_SECRET_KEY=\"你的SecretKey\"")
|
||||||
|
print("\n 方式2: 创建 .env 文件")
|
||||||
|
print(" cp .env.example .env")
|
||||||
|
print(" 然后编辑 .env 文件,填入你的密钥")
|
||||||
|
print("\n获取密钥地址: https://console.cloud.tencent.com/cam/capi")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return secret_id, secret_key
|
||||||
|
|
||||||
|
def sign_request(secret_id, secret_key, action, params):
|
||||||
|
"""
|
||||||
|
生成腾讯云API签名
|
||||||
|
文档: https://cloud.tencent.com/document/product/1427/56152
|
||||||
|
"""
|
||||||
|
# 1. 构造请求体
|
||||||
|
body = json.dumps(params)
|
||||||
|
|
||||||
|
# 2. 构造规范请求串
|
||||||
|
# 请求方法
|
||||||
|
http_request_method = "POST"
|
||||||
|
# 请求URI
|
||||||
|
canonical_uri = "/"
|
||||||
|
# 请求查询字符串(空)
|
||||||
|
canonical_querystring = ""
|
||||||
|
# 请求头
|
||||||
|
canonical_headers = f"content-type:application/json\nhost:{API_ENDPOINT}\n"
|
||||||
|
signed_headers = "content-type;host"
|
||||||
|
# 请求哈希值
|
||||||
|
hashed_request_payload = hashlib.sha256(body.encode('utf-8')).hexdigest()
|
||||||
|
canonical_request = (
|
||||||
|
http_request_method + "\n" +
|
||||||
|
canonical_uri + "\n" +
|
||||||
|
canonical_querystring + "\n" +
|
||||||
|
canonical_headers + "\n" +
|
||||||
|
signed_headers + "\n" +
|
||||||
|
hashed_request_payload
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3. 构造待签名字符串
|
||||||
|
algorithm = "TC3-HMAC-SHA256"
|
||||||
|
timestamp = int(time.time())
|
||||||
|
date = datetime.utcfromtimestamp(timestamp).strftime('%Y-%m-%d')
|
||||||
|
credential_scope = f"{date}/{API_VERSION}/tc3_request"
|
||||||
|
hashed_canonical_request = hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
|
||||||
|
string_to_sign = (
|
||||||
|
algorithm + "\n" +
|
||||||
|
str(timestamp) + "\n" +
|
||||||
|
credential_scope + "\n" +
|
||||||
|
hashed_canonical_request
|
||||||
|
)
|
||||||
|
|
||||||
|
# 4. 计算签名
|
||||||
|
def _hmac_sha256(key, msg):
|
||||||
|
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
|
||||||
|
|
||||||
|
secret_date = _hmac_sha256(f"TC3{secret_key}".encode('utf-8'), date)
|
||||||
|
secret_service = _hmac_sha256(secret_date, API_VERSION)
|
||||||
|
secret_signing = _hmac_sha256(secret_service, "tc3_request")
|
||||||
|
signature = hmac.new(secret_signing, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()
|
||||||
|
|
||||||
|
# 5. 构造Authorization头
|
||||||
|
authorization = (
|
||||||
|
algorithm + " " +
|
||||||
|
"Credential=" + secret_id + "/" + credential_scope + ", " +
|
||||||
|
"SignedHeaders=" + signed_headers + ", " +
|
||||||
|
"Signature=" + signature
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"authorization": authorization,
|
||||||
|
"body": body,
|
||||||
|
"timestamp": timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
def call_api(action, params):
|
||||||
|
"""调用腾讯云API"""
|
||||||
|
secret_id, secret_key = get_credentials()
|
||||||
|
|
||||||
|
# 生成签名
|
||||||
|
sig = sign_request(secret_id, secret_key, action, params)
|
||||||
|
|
||||||
|
# 构造请求头
|
||||||
|
headers = {
|
||||||
|
"Authorization": sig["authorization"],
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Host": API_ENDPOINT,
|
||||||
|
"X-TC-Action": action,
|
||||||
|
"X-TC-Timestamp": str(sig["timestamp"]),
|
||||||
|
"X-TC-Version": API_VERSION,
|
||||||
|
"X-TC-Region": REGION
|
||||||
|
}
|
||||||
|
|
||||||
|
# 发送请求
|
||||||
|
url = f"https://{API_ENDPOINT}/"
|
||||||
|
response = requests.post(url, headers=headers, data=sig["body"])
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def check_domain_exists(domain):
|
||||||
|
"""检查域名是否存在"""
|
||||||
|
try:
|
||||||
|
result = call_api("DescribeDomainList", {})
|
||||||
|
domains = [d["Name"] for d in result.get("Response", {}).get("DomainList", [])]
|
||||||
|
return domain in domains
|
||||||
|
except Exception as e:
|
||||||
|
print(f"检查域名失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def create_domain(domain):
|
||||||
|
"""创建域名"""
|
||||||
|
print(f"正在创建域名: {domain}")
|
||||||
|
try:
|
||||||
|
result = call_api("CreateDomain", {"Domain": domain})
|
||||||
|
print(f"✓ 域名创建成功: {domain}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ 域名创建失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def find_record(domain, subdomain, record_type):
|
||||||
|
"""查找现有记录"""
|
||||||
|
try:
|
||||||
|
params = {
|
||||||
|
"Domain": domain,
|
||||||
|
"Subdomain": subdomain,
|
||||||
|
"RecordType": record_type
|
||||||
|
}
|
||||||
|
result = call_api("DescribeRecordList", params)
|
||||||
|
records = result.get("Response", {}).get("RecordList", [])
|
||||||
|
|
||||||
|
for record in records:
|
||||||
|
if record.get("Name") == subdomain and record.get("Type") == record_type:
|
||||||
|
return record
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"查找记录失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def create_record(domain, subdomain, record_type, value, line="默认", ttl=600, remark=""):
|
||||||
|
"""创建DNS记录"""
|
||||||
|
params = {
|
||||||
|
"Domain": domain,
|
||||||
|
"RecordType": record_type,
|
||||||
|
"RecordLine": line,
|
||||||
|
"Value": value,
|
||||||
|
"TTL": ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
# 添加子域名
|
||||||
|
if subdomain and subdomain != "@":
|
||||||
|
params["SubDomain"] = subdomain
|
||||||
|
|
||||||
|
# 添加备注
|
||||||
|
if remark:
|
||||||
|
params["Remark"] = remark
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = call_api("CreateRecord", params)
|
||||||
|
record_id = result.get("Response", {}).get("RecordId")
|
||||||
|
print(f"✓ 记录创建成功: {subdomain or '@'}.{domain} ({record_type}) → {value}")
|
||||||
|
return record_id
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ 记录创建失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def modify_record(domain, record_id, subdomain, record_type, value, line="默认", ttl=600, remark=""):
|
||||||
|
"""修改DNS记录"""
|
||||||
|
params = {
|
||||||
|
"Domain": domain,
|
||||||
|
"RecordId": record_id,
|
||||||
|
"RecordType": record_type,
|
||||||
|
"RecordLine": line,
|
||||||
|
"Value": value,
|
||||||
|
"TTL": ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
if subdomain and subdomain != "@":
|
||||||
|
params["SubDomain"] = subdomain
|
||||||
|
|
||||||
|
if remark:
|
||||||
|
params["Remark"] = remark
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = call_api("ModifyRecord", params)
|
||||||
|
print(f"✓ 记录更新成功: {subdomain or '@'}.{domain} ({record_type}) → {value}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ 记录更新失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def deploy_record(domain, subdomain, record_type, value, line="默认", ttl=600, force=False, create_domain_flag=False, remark=""):
|
||||||
|
"""部署DNS记录(创建或更新)"""
|
||||||
|
print(f"\n部署DNS记录: {subdomain or '@'}.{domain}")
|
||||||
|
print(f" 类型: {record_type}")
|
||||||
|
print(f" 值: {value}")
|
||||||
|
print(f" 线路: {line}")
|
||||||
|
print(f" TTL: {ttl}s")
|
||||||
|
|
||||||
|
# 检查域名是否存在
|
||||||
|
if not check_domain_exists(domain):
|
||||||
|
if create_domain_flag:
|
||||||
|
if not create_domain(domain):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(f"✗ 域名不存在: {domain}")
|
||||||
|
print(f" 提示: 使用 --create-domain 自动创建域名")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 查找现有记录
|
||||||
|
existing = find_record(domain, subdomain, record_type)
|
||||||
|
|
||||||
|
if existing:
|
||||||
|
if not force:
|
||||||
|
old_value = existing.get("Value", "")
|
||||||
|
print(f"\n记录已存在:")
|
||||||
|
print(f" 当前值: {old_value}")
|
||||||
|
print(f" 新值: {value}")
|
||||||
|
|
||||||
|
# 检查是否需要更新
|
||||||
|
if old_value == value:
|
||||||
|
print(" 值未变化,无需更新")
|
||||||
|
return True
|
||||||
|
|
||||||
|
response = input("\n是否更新? (y/N): ")
|
||||||
|
if response.lower() != 'y':
|
||||||
|
print(" 已取消")
|
||||||
|
return False
|
||||||
|
|
||||||
|
record_id = existing.get("RecordId")
|
||||||
|
return modify_record(domain, record_id, subdomain, record_type, value, line, ttl, remark)
|
||||||
|
else:
|
||||||
|
return create_record(domain, subdomain, record_type, value, line, ttl, remark)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='DNSPod记录快速部署', formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog='''
|
||||||
|
示例:
|
||||||
|
# 添加www的A记录
|
||||||
|
%(prog)s --domain example.com --subdomain www --type A --value 1.2.3.4
|
||||||
|
|
||||||
|
# 添加主域名记录
|
||||||
|
%(prog)s --domain example.com --subdomain @ --type A --value 1.2.3.4
|
||||||
|
|
||||||
|
# 添加CNAME记录
|
||||||
|
%(prog)s --domain example.com --subdomain cdn --type CNAME --value cdn.example.com
|
||||||
|
|
||||||
|
# 强制更新现有记录
|
||||||
|
%(prog)s --domain example.com --subdomain www --type A --value 1.2.3.5 --force
|
||||||
|
|
||||||
|
# 域名不存在时自动创建
|
||||||
|
%(prog)s --domain example.com --subdomain www --type A --value 1.2.3.4 --create-domain
|
||||||
|
''')
|
||||||
|
|
||||||
|
parser.add_argument('--domain', required=True, help='域名(如: example.com)')
|
||||||
|
parser.add_argument('--subdomain', default='@', help='子域名(默认: @ 表示主域名)')
|
||||||
|
parser.add_argument('--type', required=True, choices=['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'NS', 'SRV'], help='记录类型')
|
||||||
|
parser.add_argument('--value', required=True, help='记录值')
|
||||||
|
parser.add_argument('--line', default='默认', help='线路(默认: 默认)')
|
||||||
|
parser.add_argument('--ttl', type=int, default=600, help='TTL(秒, 默认: 600)')
|
||||||
|
parser.add_argument('--force', action='store_true', help='强制更新现有记录(不询问)')
|
||||||
|
parser.add_argument('--create-domain', action='store_true', help='域名不存在时自动创建')
|
||||||
|
parser.add_argument('--remark', default='', help='记录备注')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# 部署记录
|
||||||
|
success = deploy_record(
|
||||||
|
domain=args.domain,
|
||||||
|
subdomain=args.subdomain,
|
||||||
|
record_type=args.type,
|
||||||
|
value=args.value,
|
||||||
|
line=args.line,
|
||||||
|
ttl=args.ttl,
|
||||||
|
force=args.force,
|
||||||
|
create_domain_flag=args.create_domain,
|
||||||
|
remark=args.remark
|
||||||
|
)
|
||||||
|
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
163
scripts/deploy_service.py
Executable file
163
scripts/deploy_service.py
Executable file
@@ -0,0 +1,163 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
快速服务部署脚本
|
||||||
|
一键部署常见服务的DNS配置(Web服务、API服务、CDN等)
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from deploy_record import deploy_record, load_env
|
||||||
|
|
||||||
|
# 加载 .env
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
def deploy_web_service(domain, ip, include_wildcard=False, line="默认", ttl=600):
|
||||||
|
"""部署Web服务(主域名 + www + 可选泛域名)"""
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"部署Web服务: {domain}")
|
||||||
|
print(f"目标IP: {ip}")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
success_count = 0
|
||||||
|
total_count = 2 + (1 if include_wildcard else 0)
|
||||||
|
|
||||||
|
# 1. 主域名 @
|
||||||
|
if deploy_record(domain, '@', 'A', ip, line, ttl, force=True, remark='主域名'):
|
||||||
|
success_count += 1
|
||||||
|
|
||||||
|
# 2. www子域名
|
||||||
|
if deploy_record(domain, 'www', 'A', ip, line, ttl, force=True, remark='Web服务'):
|
||||||
|
success_count += 1
|
||||||
|
|
||||||
|
# 3. 泛域名 *(可选)
|
||||||
|
if include_wildcard:
|
||||||
|
if deploy_record(domain, '*', 'A', ip, line, ttl, force=True, remark='泛域名'):
|
||||||
|
success_count += 1
|
||||||
|
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"Web服务部署完成: {success_count}/{total_count} 成功")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
return success_count == total_count
|
||||||
|
|
||||||
|
def deploy_api_service(domain, ip, subdomain="api", line="默认", ttl=600):
|
||||||
|
"""部署API服务"""
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"部署API服务: {subdomain}.{domain}")
|
||||||
|
print(f"目标IP: {ip}")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
success = deploy_record(domain, subdomain, 'A', ip, line, ttl, force=True, remark='API服务')
|
||||||
|
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"API服务部署{'成功' if success else '失败'}")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
|
def deploy_cdn_service(domain, cdn_cname, subdomain="cdn", line="默认", ttl=600):
|
||||||
|
"""部署CDN加速"""
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"部署CDN加速: {subdomain}.{domain}")
|
||||||
|
print(f"CNAME: {cdn_cname}")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
success = deploy_record(domain, subdomain, 'CNAME', cdn_cname, line, ttl, force=True, remark='CDN加速')
|
||||||
|
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"CDN部署{'成功' if success else '失败'}")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
|
def deploy_mx_service(domain, mx_server, priority=10, line="默认"):
|
||||||
|
"""部署邮件服务(MX记录)"""
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"部署邮件服务: {domain}")
|
||||||
|
print(f"MX服务器: {mx_server}")
|
||||||
|
print(f"优先级: {priority}")
|
||||||
|
print(f"{'='*50}\n")
|
||||||
|
|
||||||
|
# 注意: MX记录需要特殊处理,这里简化处理
|
||||||
|
# 实际需要调用MX专用的创建接口
|
||||||
|
print(f"提示: MX记录部署需要手动配置")
|
||||||
|
print(f" 记录类型: MX")
|
||||||
|
print(f" 主机记录: @")
|
||||||
|
print(f" 记录值: {mx_server}")
|
||||||
|
print(f" 优先级: {priority}")
|
||||||
|
print(f" 线路: {line}\n")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='快速服务部署', formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog='''
|
||||||
|
服务类型:
|
||||||
|
web - Web服务(@ + www)
|
||||||
|
api - API服务(api子域名)
|
||||||
|
cdn - CDN加速(CNAME记录)
|
||||||
|
mx - 邮件服务(MX记录)
|
||||||
|
|
||||||
|
示例:
|
||||||
|
# 部署Web服务
|
||||||
|
%(prog)s --domain example.com --service web --ip 1.2.3.4
|
||||||
|
|
||||||
|
# 部署Web服务(含泛域名)
|
||||||
|
%(prog)s --domain example.com --service web --ip 1.2.3.4 --wildcard
|
||||||
|
|
||||||
|
# 部署API服务
|
||||||
|
%(prog)s --domain example.com --service api --ip 1.2.3.5 --subdomain api
|
||||||
|
|
||||||
|
# 部署CDN
|
||||||
|
%(prog)s --domain example.com --service cdn --cname cdn.example.com.cdn.dnsv1.com
|
||||||
|
|
||||||
|
# 部署邮件服务
|
||||||
|
%(prog)s --domain example.com --service mx --mx-server mx.example.com --priority 10
|
||||||
|
''')
|
||||||
|
|
||||||
|
parser.add_argument('--domain', required=True, help='域名(如: example.com)')
|
||||||
|
parser.add_argument('--service', required=True, choices=['web', 'api', 'cdn', 'mx'], help='服务类型')
|
||||||
|
parser.add_argument('--ip', help='目标IP地址(A记录)')
|
||||||
|
parser.add_argument('--cname', help='CNAME目标域名')
|
||||||
|
parser.add_argument('--mx-server', help='MX服务器地址')
|
||||||
|
parser.add_argument('--priority', type=int, default=10, help='MX优先级(默认: 10)')
|
||||||
|
parser.add_argument('--subdomain', default='api', help='API子域名(默认: api)')
|
||||||
|
parser.add_argument('--cdn-subdomain', default='cdn', help='CDN子域名(默认: cdn)')
|
||||||
|
parser.add_argument('--line', default='默认', help='线路(默认: 默认)')
|
||||||
|
parser.add_argument('--ttl', type=int, default=600, help='TTL(秒, 默认: 600)')
|
||||||
|
parser.add_argument('--wildcard', action='store_true', help='Web服务是否添加泛域名解析(*.domain)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
success = False
|
||||||
|
|
||||||
|
if args.service == 'web':
|
||||||
|
if not args.ip:
|
||||||
|
print("错误: Web服务需要指定 --ip 参数")
|
||||||
|
sys.exit(1)
|
||||||
|
success = deploy_web_service(args.domain, args.ip, args.wildcard, args.line, args.ttl)
|
||||||
|
|
||||||
|
elif args.service == 'api':
|
||||||
|
if not args.ip:
|
||||||
|
print("错误: API服务需要指定 --ip 参数")
|
||||||
|
sys.exit(1)
|
||||||
|
success = deploy_api_service(args.domain, args.ip, args.subdomain, args.line, args.ttl)
|
||||||
|
|
||||||
|
elif args.service == 'cdn':
|
||||||
|
if not args.cname:
|
||||||
|
print("错误: CDN服务需要指定 --cname 参数")
|
||||||
|
sys.exit(1)
|
||||||
|
success = deploy_cdn_service(args.domain, args.cname, args.cdn_subdomain, args.line, args.ttl)
|
||||||
|
|
||||||
|
elif args.service == 'mx':
|
||||||
|
if not args.mx_server:
|
||||||
|
print("错误: 邮件服务需要指定 --mx-server 参数")
|
||||||
|
sys.exit(1)
|
||||||
|
success = deploy_mx_service(args.domain, args.mx_server, args.priority, args.line)
|
||||||
|
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
77
scripts/list_records.py
Executable file
77
scripts/list_records.py
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
DNS记录列表查询脚本
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
from deploy_record import call_api, load_env
|
||||||
|
|
||||||
|
# 加载 .env
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
def list_records(domain, record_type=None, subdomain=None):
|
||||||
|
"""查询DNS记录列表"""
|
||||||
|
params = {"Domain": domain}
|
||||||
|
|
||||||
|
if record_type:
|
||||||
|
params["RecordType"] = record_type
|
||||||
|
if subdomain:
|
||||||
|
params["Subdomain"] = subdomain
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = call_api("DescribeRecordList", params)
|
||||||
|
records = result.get("Response", {}).get("RecordList", [])
|
||||||
|
|
||||||
|
if not records:
|
||||||
|
print(f"\n没有找到记录")
|
||||||
|
return []
|
||||||
|
|
||||||
|
print(f"\n{'='*80}")
|
||||||
|
print(f"DNS记录列表: {domain}")
|
||||||
|
print(f"{'='*80}\n")
|
||||||
|
|
||||||
|
# 表头
|
||||||
|
print(f"{'主机记录':<20} {'类型':<10} {'记录值':<30} {'线路':<10} {'TTL':<8} {'状态':<6}")
|
||||||
|
print(f"{'-'*80}")
|
||||||
|
|
||||||
|
# 记录列表
|
||||||
|
for record in records:
|
||||||
|
name = record.get("Name", "")
|
||||||
|
record_type = record.get("Type", "")
|
||||||
|
value = record.get("Value", "")
|
||||||
|
line = record.get("Line", "")
|
||||||
|
ttl = record.get("TTL", 0)
|
||||||
|
status = "启用" if record.get("Enabled", 1) == 1 else "禁用"
|
||||||
|
|
||||||
|
# 截断过长的值
|
||||||
|
if len(value) > 28:
|
||||||
|
value = value[:28] + ".."
|
||||||
|
|
||||||
|
print(f"{name:<20} {record_type:<10} {value:<30} {line:<10} {ttl:<8} {status:<6}")
|
||||||
|
|
||||||
|
print(f"{'-'*80}")
|
||||||
|
print(f"总计: {len(records)} 条记录\n")
|
||||||
|
|
||||||
|
return records
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"查询失败: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='查询DNS记录列表')
|
||||||
|
|
||||||
|
parser.add_argument('--domain', required=True, help='域名(如: example.com)')
|
||||||
|
parser.add_argument('--type', help='筛选记录类型')
|
||||||
|
parser.add_argument('--subdomain', help='筛选子域名')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
list_records(args.domain, args.type, args.subdomain)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user