84 lines
4.6 KiB
JSON
84 lines
4.6 KiB
JSON
{
|
|
"name": "備份驗證與還原測試",
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"rule": {
|
|
"interval": [
|
|
{
|
|
"field": "cronExpression",
|
|
"expression": "0 4 * * 0"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"id": "schedule",
|
|
"name": "每週日 04:00",
|
|
"type": "n8n-nodes-base.scheduleTrigger",
|
|
"typeVersion": 1.2,
|
|
"position": [240, 300]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"command": "#!/bin/bash\nset -e\n\n# 備份驗證腳本\nBACKUP_DIR=\"/home/wooo/backups/postgres\"\nTEST_DB=\"momo_backup_test\"\nREPORT=\"\"\n\n# 1. 找到最新備份\nLATEST_BACKUP=$(ls -t ${BACKUP_DIR}/*.sql.gz 2>/dev/null | head -1)\n\nif [ -z \"$LATEST_BACKUP\" ]; then\n echo '{\"success\": false, \"error\": \"找不到備份檔案\"}'\n exit 1\nfi\n\nBACKUP_DATE=$(stat -c %Y \"$LATEST_BACKUP\" 2>/dev/null || stat -f %m \"$LATEST_BACKUP\")\nBACKUP_SIZE=$(ls -lh \"$LATEST_BACKUP\" | awk '{print $5}')\n\n# 2. 建立測試資料庫\nkubectl exec -n momo momo-postgres-0 -- psql -U momo -c \"DROP DATABASE IF EXISTS ${TEST_DB};\" 2>/dev/null || true\nkubectl exec -n momo momo-postgres-0 -- psql -U momo -c \"CREATE DATABASE ${TEST_DB};\" 2>/dev/null\n\n# 3. 還原備份到測試資料庫\ngunzip -c \"$LATEST_BACKUP\" | kubectl exec -i -n momo momo-postgres-0 -- psql -U momo -d ${TEST_DB} 2>/dev/null\n\n# 4. 驗證還原結果\nTABLE_COUNT=$(kubectl exec -n momo momo-postgres-0 -- psql -U momo -d ${TEST_DB} -t -c \\\n \"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';\" 2>/dev/null | tr -d ' ')\n\nPRODUCT_COUNT=$(kubectl exec -n momo momo-postgres-0 -- psql -U momo -d ${TEST_DB} -t -c \\\n \"SELECT COUNT(*) FROM products;\" 2>/dev/null | tr -d ' ' || echo '0')\n\n# 5. 清理測試資料庫\nkubectl exec -n momo momo-postgres-0 -- psql -U momo -c \"DROP DATABASE IF EXISTS ${TEST_DB};\" 2>/dev/null\n\n# 6. 輸出結果\necho \"{\n \\\"success\\\": true,\n \\\"backupFile\\\": \\\"$(basename $LATEST_BACKUP)\\\",\n \\\"backupSize\\\": \\\"${BACKUP_SIZE}\\\",\n \\\"tableCount\\\": ${TABLE_COUNT:-0},\n \\\"productCount\\\": ${PRODUCT_COUNT:-0},\n \\\"verifiedAt\\\": \\\"$(date -Iseconds)\\\"\n}\"",
|
|
"cwd": "/home/wooo"
|
|
},
|
|
"id": "verify-backup",
|
|
"name": "驗證備份",
|
|
"type": "n8n-nodes-base.executeCommand",
|
|
"typeVersion": 1,
|
|
"position": [460, 300],
|
|
"continueOnFail": true
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const output = $input.first().json.stdout || '';\nconst stderr = $input.first().json.stderr || '';\nconst exitCode = $input.first().json.exitCode;\nconst now = new Date().toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });\n\nlet result;\ntry {\n result = JSON.parse(output.trim());\n} catch (e) {\n result = { success: false, error: stderr || output };\n}\n\nlet message = '';\nif (result.success) {\n message = `✅ <b>每週備份驗證成功</b>\\n\\n`;\n message += `📁 備份檔案: ${result.backupFile}\\n`;\n message += `📊 檔案大小: ${result.backupSize}\\n`;\n message += `📋 資料表數: ${result.tableCount}\\n`;\n message += `📦 商品數量: ${result.productCount}\\n`;\n message += `⏰ 驗證時間: ${now}`;\n} else {\n message = `🔴 <b>備份驗證失敗</b>\\n\\n`;\n message += `❌ 錯誤: ${result.error || '未知錯誤'}\\n`;\n message += `⏰ 時間: ${now}`;\n}\n\nreturn [{ json: { success: result.success, message } }];"
|
|
},
|
|
"id": "process-result",
|
|
"name": "處理結果",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [680, 300]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "https://api.telegram.org/bot<TELEGRAM_BOT_TOKEN>/sendMessage",
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={\n \"chat_id\": \"5619078117\",\n \"parse_mode\": \"HTML\",\n \"text\": \"{{ $json.message }}\"\n}",
|
|
"options": {}
|
|
},
|
|
"id": "telegram",
|
|
"name": "發送報告",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [900, 300]
|
|
}
|
|
],
|
|
"connections": {
|
|
"每週日 04:00": {
|
|
"main": [
|
|
[{ "node": "驗證備份", "type": "main", "index": 0 }]
|
|
]
|
|
},
|
|
"驗證備份": {
|
|
"main": [
|
|
[{ "node": "處理結果", "type": "main", "index": 0 }]
|
|
]
|
|
},
|
|
"處理結果": {
|
|
"main": [
|
|
[{ "node": "發送報告", "type": "main", "index": 0 }]
|
|
]
|
|
}
|
|
},
|
|
"settings": {
|
|
"executionOrder": "v1"
|
|
},
|
|
"staticData": null,
|
|
"tags": [],
|
|
"triggerCount": 0,
|
|
"updatedAt": "2026-02-07T17:00:00.000Z",
|
|
"versionId": "1"
|
|
}
|