Skip to content

Commit d0dc859

Browse files
committed
feat: 添加插件开发指南,提供 RedC 插件编写的详细说明和示例
1 parent 911cd5f commit d0dc859

3 files changed

Lines changed: 251 additions & 0 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,8 @@ This repository uses GitHub Actions to automatically check for sensitive informa
5454
- **CI/CD Integration**: Scanning is triggered on every push and pull request
5555
- **Leak Prevention**: CI fails and blocks merging when sensitive information is detected
5656

57+
## Plugin Development
58+
59+
If you want to write your own RedC plugin (lifecycle hooks, config generation, file upload, etc.), see the [Plugin Development Guide](doc/plugin-development.md).
60+
5761
⚠️ **Important**: Do not write real AK/SK, passwords, or other sensitive information directly into the code. Use environment variables or configuration files to manage sensitive information.

README_CN.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,7 @@ vultr (不推荐使用)
6666
- **防止泄露**: 检测到敏感信息时,CI 会失败并阻止合并
6767

6868
⚠️ **重要**: 请勿将真实的 AK/SK、密码等敏感信息直接写入代码中。应使用环境变量或配置文件管理敏感信息。
69+
70+
## 插件开发
71+
72+
如果需要编写自己的 RedC 插件(生命周期钩子、配置生成、文件上传等),请参阅 [插件开发指南](doc/plugin-development.md)

doc/plugin-development.md

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# RedC 插件开发指南
2+
3+
本文档介绍如何编写一个 RedC 插件。插件可以在场景生命周期的关键节点(部署前/后、销毁前/后)执行自定义脚本,实现配置生成、文件上传、DNS 更新、Webhook 通知等扩展功能。
4+
5+
> 完整示例请参考 [redc-plugin-example](../plugins/redc-plugin-example/),生产级参考请看 [redc-plugin-clash-config](../plugins/redc-plugin-clash-config/)[redc-plugin-upload-r2](../plugins/redc-plugin-upload-r2/)[redc-plugin-cloudflare-dns](../plugins/redc-plugin-cloudflare-dns/)
6+
7+
## 目录结构
8+
9+
```
10+
redc-plugin-your-name/
11+
├── plugin.json # 必须 — 插件清单文件
12+
├── README.md # 推荐 — 使用说明
13+
├── hooks/ # 可选 — 生命周期钩子脚本
14+
│ ├── pre-plan.sh
15+
│ ├── post-plan.sh
16+
│ ├── pre-apply.sh
17+
│ ├── post-apply.sh # 最常用:部署完成后执行
18+
│ ├── pre-destroy.sh
19+
│ └── post-destroy.sh
20+
└── templates/ # 可选 — 附带的 Terraform 模板
21+
```
22+
23+
插件安装后存放在 `~/.redc/plugins/<plugin-name>/` 目录下。
24+
25+
## plugin.json 完整字段说明
26+
27+
`plugin.json` 是插件的唯一必须文件,定义了插件的元信息、能力声明和配置参数。
28+
29+
```jsonc
30+
{
31+
// ── 基础信息 ──
32+
"name": "redc-plugin-your-name", // 必填,插件名称,建议 redc-plugin- 前缀
33+
"version": "1.0.0", // 必填,语义化版本号
34+
"description": "插件功能的中文描述", // 必填,中文描述
35+
"description_en": "English description", // 可选,英文描述
36+
"author": "your-name", // 可选,作者
37+
"homepage": "https://github.com/...", // 可选,项目主页
38+
"category": "proxy", // 可选,分类(proxy/dns/storage/monitoring/example 等)
39+
"tags": ["clash", "proxy"], // 可选,标签数组,用于搜索和分类
40+
"min_redc_version": "3.1.0", // 可选,要求的最低 RedC 版本
41+
42+
// ── 能力声明 ──
43+
"capabilities": {
44+
"hooks": { // 生命周期钩子,key 为钩子点,value 为脚本相对路径
45+
"post-apply": "hooks/post-apply.sh",
46+
"pre-destroy": "hooks/pre-destroy.sh"
47+
},
48+
"templates": ["templates/*.tf"], // 可选,附带的 Terraform 模板(glob 模式)
49+
"userdata": ["userdata/*.sh"] // 可选,附带的 Userdata 脚本(glob 模式)
50+
},
51+
52+
// ── 配置参数(可选)──
53+
// 声明后 GUI 会自动渲染配置表单,用户可在「插件管理」页面填写
54+
"config_schema": {
55+
"notify_url": {
56+
"type": "string", // 类型:string / number / boolean
57+
"required": false, // 是否必填
58+
"description": "Webhook 通知地址", // 参数说明
59+
"default": "" // 默认值
60+
},
61+
"enable_log": {
62+
"type": "boolean",
63+
"required": false,
64+
"description": "是否记录详细日志",
65+
"default": "true"
66+
}
67+
}
68+
}
69+
```
70+
71+
## 生命周期钩子
72+
73+
### 6 个钩子点
74+
75+
| 钩子点 | 触发时机 | 典型用途 |
76+
|--------|---------|---------|
77+
| `pre-plan` | `terraform plan` 之前 | 预检查、参数验证 |
78+
| `post-plan` | `terraform plan` 之后 | 审查计划输出 |
79+
| `pre-apply` | `terraform apply` 之前 | 准备外部资源 |
80+
| `post-apply` | `terraform apply` 之后 | 生成配置、上传文件、更新 DNS、发通知 |
81+
| `pre-destroy` | `terraform destroy` 之前 | 清理外部资源(DNS 记录、文件等) |
82+
| `post-destroy` | `terraform destroy` 之后 | 发送销毁通知 |
83+
84+
### 执行规则
85+
86+
- 每个钩子脚本最长执行 **5 分钟**,超时自动终止
87+
- 钩子失败**不会阻断**后续流程,错误会记录到日志并继续执行下一个插件的钩子
88+
- 同一场景绑定多个插件时,按 `case.json``redc_plugins` 的声明顺序执行
89+
- 脚本通过 `bash` 执行,工作目录为插件目录
90+
91+
### 环境变量
92+
93+
钩子脚本可通过以下环境变量获取场景信息和插件配置:
94+
95+
#### 场景信息
96+
97+
| 变量 | 说明 | 示例 |
98+
|------|------|------|
99+
| `REDC_HOOK_POINT` | 当前钩子点 | `post-apply` |
100+
| `REDC_PLUGIN_NAME` | 插件名称 | `redc-plugin-clash-config` |
101+
| `REDC_PLUGIN_DIR` | 插件目录绝对路径 | `/Users/xxx/.redc/plugins/redc-plugin-clash-config` |
102+
| `REDC_CASE_NAME` | 场景名称 | `proxy-01` |
103+
| `REDC_CASE_PATH` | 场景目录绝对路径 | `/Users/xxx/.redc/project/xxx/proxy-01` |
104+
| `REDC_CASE_TEMPLATE` | 场景模板类型 | `aliyun/proxy` |
105+
| `REDC_CASE_STATE` | 场景状态 | `running` |
106+
| `REDC_OUTPUT_JSON` | Terraform 输出(JSON 格式) | `{"public_ip":{"value":["1.2.3.4"],...}}` |
107+
| `REDC_CASE_VARS` | 场景参数(JSON 格式) | `{"region":"cn-beijing","node":"2"}` |
108+
109+
#### 插件配置
110+
111+
| 变量 | 说明 |
112+
|------|------|
113+
| `REDC_PLUGIN_CONFIG` | 完整配置(JSON 格式),如 `{"notify_url":"https://...","enable_log":true}` |
114+
| `REDC_PLUGIN_CONFIG_<KEY>` | 单个配置值,key 转为大写并将 `-` 替换为 `_` |
115+
116+
**配置 key 转换规则:** `notify_url``REDC_PLUGIN_CONFIG_NOTIFY_URL``enable-log``REDC_PLUGIN_CONFIG_ENABLE_LOG`
117+
118+
### REDC_OUTPUT 协议
119+
120+
钩子脚本可以通过 stdout 输出特殊格式的行,将数据回传给 RedC:
121+
122+
```bash
123+
echo "REDC_OUTPUT:clash_config_url=https://example.com/config.yaml"
124+
echo "REDC_OUTPUT:node_count=3"
125+
```
126+
127+
格式为 `REDC_OUTPUT:key=value`,每行一个键值对。这些输出会:
128+
1. 持久化到场景目录下的 `plugin_outputs.json`
129+
2. 合并到 GUI 的场景输出面板中展示
130+
3. 可被后续插件和 AI Agent 读取
131+
132+
`REDC_OUTPUT:` 前缀的 stdout 内容会作为普通日志输出。
133+
134+
## 编写钩子脚本示例
135+
136+
一个典型的 `post-apply` 钩子:
137+
138+
```bash
139+
#!/bin/bash
140+
set -euo pipefail
141+
142+
echo "[my-plugin] post-apply hook triggered for ${REDC_CASE_NAME}"
143+
144+
# 1. 从 Terraform 输出获取 IP
145+
IPS=$(echo "$REDC_OUTPUT_JSON" | jq -r '.public_ip.value[]' 2>/dev/null)
146+
if [ -z "$IPS" ]; then
147+
echo "[my-plugin] no IPs found in outputs, skipping"
148+
exit 0
149+
fi
150+
151+
# 2. 读取插件配置
152+
PORT="${REDC_PLUGIN_CONFIG_PORT:-8388}"
153+
154+
# 3. 执行业务逻辑(示例:生成配置文件)
155+
CONFIG_FILE="${REDC_CASE_PATH}/my-config.yaml"
156+
echo "servers:" > "$CONFIG_FILE"
157+
for ip in $IPS; do
158+
echo " - address: $ip:$PORT" >> "$CONFIG_FILE"
159+
done
160+
161+
# 4. 通过 REDC_OUTPUT 回传结果到 GUI
162+
echo "REDC_OUTPUT:config_file=${CONFIG_FILE}"
163+
echo "REDC_OUTPUT:server_count=$(echo "$IPS" | wc -l | tr -d ' ')"
164+
165+
# 5. 可选:Webhook 通知
166+
if [ -n "${REDC_PLUGIN_CONFIG_NOTIFY_URL:-}" ]; then
167+
curl -s -X POST "$REDC_PLUGIN_CONFIG_NOTIFY_URL" \
168+
-H "Content-Type: application/json" \
169+
-d "{\"event\":\"deployed\",\"case\":\"${REDC_CASE_NAME}\",\"ips\":\"${IPS}\"}" \
170+
--max-time 10 || echo "[my-plugin] webhook failed (non-fatal)"
171+
fi
172+
173+
echo "[my-plugin] done"
174+
```
175+
176+
## 场景绑定插件
177+
178+
在模板的 `case.json` 中通过 `redc_plugins` 字段声明依赖的插件(逗号分隔):
179+
180+
```json
181+
{
182+
"name": "proxy",
183+
"description": "多节点代理场景",
184+
"redc_plugins": "redc-plugin-clash-config,redc-plugin-upload-r2",
185+
"template": "preset"
186+
}
187+
```
188+
189+
场景启动时,RedC 会按声明顺序执行这些插件的钩子。如果用户未安装声明的插件,GUI 会在启动前弹窗提醒。
190+
191+
## 安装与调试
192+
193+
### 安装方式
194+
195+
```bash
196+
# 从 Git 仓库安装
197+
redc plugin install https://github.com/your-org/redc-plugin-your-name
198+
199+
# 从本地路径安装(开发调试用)
200+
redc plugin install /path/to/redc-plugin-your-name
201+
202+
# 从 ZIP URL 安装
203+
redc plugin install https://example.com/redc-plugin-your-name.zip
204+
```
205+
206+
GUI 中可在「插件管理」页面输入上述地址安装。
207+
208+
### 常用命令
209+
210+
```bash
211+
redc plugin list # 列出已安装插件
212+
redc plugin info <name> # 查看插件详情
213+
redc plugin enable <name> # 启用插件
214+
redc plugin disable <name> # 禁用插件(在插件目录创建 .disabled 标记文件)
215+
redc plugin update <name> # 更新插件(Git: pull,ZIP: 重新下载)
216+
redc plugin uninstall <name> # 卸载插件
217+
```
218+
219+
### 调试技巧
220+
221+
1. **本地安装开发:** 开发时用 `redc plugin install /local/path` 安装,修改代码后 `redc plugin update <name>` 更新
222+
2. **查看日志:** 钩子脚本的 stdout/stderr 会输出到 RedC 日志和 GUI 控制台
223+
3. **手动测试钩子:** 设置好环境变量后直接运行脚本
224+
```bash
225+
REDC_CASE_NAME=test REDC_OUTPUT_JSON='{"public_ip":{"value":["1.2.3.4"]}}' \
226+
bash hooks/post-apply.sh
227+
```
228+
4. **检查输出:** 查看场景目录下的 `plugin_outputs.json` 确认 REDC_OUTPUT 是否正确写入
229+
230+
## 发布到插件市场
231+
232+
1. 将插件推送到公开的 Git 仓库
233+
2.[redc-template](https://github.com/wgpsec/redc-template) 提交 PR,将插件目录放到 `plugins/`
234+
3. 合并后 GitHub Actions 会自动更新插件市场索引,用户即可在 GUI 的插件市场中发现和安装
235+
236+
## 现有插件参考
237+
238+
| 插件 | 功能 | 钩子 |
239+
|------|------|------|
240+
| [redc-plugin-clash-config](../plugins/redc-plugin-clash-config/) | 部署后生成 Clash 代理配置 | post-apply |
241+
| [redc-plugin-upload-r2](../plugins/redc-plugin-upload-r2/) | 将生成的文件上传到 Cloudflare R2 | post-apply |
242+
| [redc-plugin-cloudflare-dns](../plugins/redc-plugin-cloudflare-dns/) | 部署后更新 Cloudflare DNS 记录 | post-apply, pre-destroy |
243+
| [redc-plugin-example](../plugins/redc-plugin-example/) | 示例插件(日志 + Webhook) | post-apply, pre-destroy |

0 commit comments

Comments
 (0)