Skip to content

Commit 287b249

Browse files
authored
Merge pull request #14 from oldjs/go-callback
Go callback
2 parents f372e6c + 2db411d commit 287b249

File tree

18 files changed

+1315
-1
lines changed

18 files changed

+1315
-1
lines changed

.github/workflows/go-test.yml

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
name: Go Callback Handler Test
2+
3+
on:
4+
push:
5+
branches: [main, go-callback]
6+
pull_request:
7+
branches: [main, go-callback]
8+
9+
jobs:
10+
build-and-test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Go
18+
uses: actions/setup-go@v5
19+
with:
20+
go-version: "1.22"
21+
22+
- name: Cache Go modules and build
23+
uses: actions/cache@v4
24+
with:
25+
path: |
26+
~/go/pkg/mod
27+
~/.cache/go-build
28+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
29+
30+
- name: Install dependencies
31+
run: go mod download
32+
33+
- name: Build application
34+
run: go build -v -o ./myapp ./go/callback/main.go
35+
36+
- name: Create test files
37+
run: |
38+
echo "port=8080" > backup.conf
39+
echo "callback_secret=my-test-secret" >> backup.conf
40+
echo "scriptpath=./docker-backup.sh" >> backup.conf
41+
42+
- name: Run integration test
43+
run: |
44+
# Start a test container for backup
45+
echo "Starting a test Docker container..."
46+
docker run -d --name test-container nginx:alpine
47+
echo "Test container started."
48+
49+
# Start the callback handler application in the background
50+
nohup ./myapp > app.log 2>&1 &
51+
52+
# Health check - wait for the server to be ready (max 30 seconds)
53+
for i in {1..30}; do
54+
if curl -s http://localhost:8080 >/dev/null; then
55+
echo "Server is ready"
56+
break
57+
fi
58+
echo "Waiting for server to be ready..."
59+
sleep 1
60+
done
61+
62+
# Prepare and send a simulated external callback (POST request)
63+
# Include the test container name in the args
64+
SIGNATURE=$(echo -n '{"args":["test-container"]}' | openssl dgst -sha256 -hmac "my-test-secret" | sed 's/^.* //')
65+
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST http://localhost:8080/backup \
66+
-H "Content-Type: application/json" \
67+
-H "X-Signature: sha256=$SIGNATURE" \
68+
-d '{"args":["test-container"]}')
69+
70+
# Extract response body and status code
71+
RESPONSE_BODY=$(echo "$RESPONSE" | head -n -1)
72+
STATUS_CODE=$(echo "$RESPONSE" | tail -n 1)
73+
74+
# Verify response
75+
if [ "$STATUS_CODE" != "200" ]; then
76+
echo "Test failed: Expected status code 200, got $STATUS_CODE"
77+
echo "Response: $RESPONSE_BODY"
78+
# Output app logs for debugging
79+
echo "=== App logs ==="
80+
cat app.log
81+
echo "=== End of app logs ==="
82+
# Output Docker logs for the test container
83+
echo "=== Test container logs ==="
84+
docker logs test-container || true
85+
echo "=== End of test container logs ==="
86+
exit 1
87+
fi
88+
89+
if [[ "$RESPONSE_BODY" != *"Backup initiated successfully"* ]]; then
90+
echo "Test failed: Expected response body to contain 'Backup initiated successfully'"
91+
echo "Response: $RESPONSE_BODY"
92+
# Output app logs for debugging
93+
echo "=== App logs ==="
94+
cat app.log
95+
echo "=== End of app logs ==="
96+
# Output Docker logs for the test container
97+
echo "=== Test container logs ==="
98+
docker logs test-container || true
99+
echo "=== End of test container logs ==="
100+
exit 1
101+
fi
102+
103+
echo "Callback handler test passed"
104+
105+
# Cleanup
106+
killall myapp || true
107+
docker rm -f test-container || true
108+
109+
- name: Output application logs
110+
if: always()
111+
run: cat app.log
112+
113+
- name: List backup artifacts (if any)
114+
if: always()
115+
run: |
116+
echo "=== Listing Docker backup artifacts ==="
117+
# List directories that match the backup pattern created by docker-backup.sh
118+
echo "Backup directories:"
119+
ls -la /tmp/docker-backups/ 2>/dev/null || echo "No backup directory found at /tmp/docker-backups/"
120+
121+
# If backup directories exist, show their contents
122+
if [[ -d "/tmp/docker-backups" ]]; then
123+
for backup_dir in /tmp/docker-backups/*/; do
124+
if [[ -d "$backup_dir" ]]; then
125+
echo "Contents of $backup_dir:"
126+
ls -la "$backup_dir"
127+
echo "---"
128+
fi
129+
done
130+
fi
131+
echo "=== End of Docker backup artifact listing ==="

backup.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,10 @@ RUN_BACKUP_VERIFICATION=true
214214
# - CONTAINER_EXCLUDE_MOUNTS=true/false
215215
# - CONTAINER_PAUSE_DURING_BACKUP=true/false
216216
# - CONTAINER_PRE_BACKUP_SCRIPT="/path/to/script.sh"
217-
# - CONTAINER_POST_BACKUP_SCRIPT="/path/to/script.sh"
217+
# - CONTAINER_POST_BACKUP_SCRIPT="/path/to/script.sh"
218+
# ============================================================================
219+
# 回调配置
220+
# ============================================================================
221+
222+
# 回调密钥(用于验证回调请求的安全性)
223+
callback_secret="a_very_secure_random_string_12345!@#$%^&*()"

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module dcoker_backup_script
2+
3+
go 1.24.4

go/callback/README.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# 安全回调服务器
2+
3+
## 功能简介
4+
5+
此工具提供了一个带签名验证的安全回调接口,用于触发 Docker 容器和卷的备份操作。
6+
7+
## 完整使用指南
8+
9+
有关如何安装、配置和使用此回调服务器的完整指南,请参阅 [USAGE.md](USAGE.md) 文件。
10+
11+
## 配置
12+
13+
在使用此回调服务器之前,您需要在项目根目录下的 `backup.conf` 文件中配置 `callback_secret`
14+
15+
```bash
16+
# backup.conf
17+
callback_secret=your_secret_key_here
18+
```
19+
20+
## 编译服务器
21+
22+
`go/callback/` 目录中运行以下命令来编译服务器:
23+
24+
```bash
25+
go build -o callback_server.exe .
26+
```
27+
28+
这将生成一个名为 `callback_server.exe` 的可执行文件(在 Windows 上)。
29+
30+
## 运行服务器
31+
32+
`go/callback/` 目录中运行生成的可执行文件:
33+
34+
```bash
35+
./callback_server.exe
36+
```
37+
38+
服务器将在 `localhost:47731` 启动。
39+
40+
## API 端点
41+
42+
### `POST /backup`
43+
44+
此端点用于触发备份操作。
45+
46+
**Headers:**
47+
48+
- `X-Signature`: 请求签名,用于验证请求来源。签名是使用配置的 `callback_secret` 对请求体进行 HMAC-SHA256 计算得出的。
49+
50+
**Request Body:**
51+
52+
```json
53+
{
54+
"args": ["arg1", "arg2"]
55+
}
56+
```
57+
58+
- `args`: 传递给备份脚本的参数数组。
59+
60+
## 编译并使用客户端示例
61+
62+
`go/callback/` 目录中运行以下命令来编译客户端示例:
63+
64+
```bash
65+
go build -o client_example.exe client_example.go
66+
```
67+
68+
由于 `client_example.go` 文件被构建标签 `//go:build ignore` 标记,所以编译时必须显式指定文件名。
69+
70+
然后可以使用以下命令来调用回调接口:
71+
72+
```bash
73+
./client_example.exe -a --volumes
74+
```
75+
76+
## Client Examples
77+
78+
### Python 示例
79+
80+
依赖安装: `pip install requests`,运行命令: `python client_example.py [args...]`
81+
82+
### JavaScript (Node.js) 示例
83+
84+
依赖安装: 无需额外依赖,运行命令: `node client_example.js [args...]`
85+
86+
### TypeScript 示例
87+
88+
依赖安装: `npm install -g typescript ts-node`,运行命令: `ts-node client_example.ts [args...]`
89+
90+
### cURL 示例 (Linux/macOS)
91+
92+
您也可以使用 `curl` 和其他命令行工具直接触发回调。这是一个一键执行的示例,它会自动从 `backup.conf` 读取密钥、生成签名并发起请求:
93+
94+
```shell
95+
# 注意:请在 go/callback 目录下运行此命令
96+
SECRET=$(grep 'callback_secret' ../../backup.conf | cut -d '"' -f 2)
97+
BODY='{"args": ["-a", "--volumes"]}'
98+
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -binary | base64)
99+
100+
curl -X POST \
101+
-H "Content-Type: application/json" \
102+
-H "X-Signature: $SIGNATURE" \
103+
-d "$BODY" \
104+
http://localhost:47731/backup
105+
```
106+
107+
## 文档导航
108+
109+
- [完整使用指南 (USAGE.md)](USAGE.md)
110+
- [GitHub Actions 工作流文档 (WORKFLOW_zh-CN.md)](WORKFLOW_zh-CN.md)

0 commit comments

Comments
 (0)