281 lines
7.8 KiB
Bash
Executable File
281 lines
7.8 KiB
Bash
Executable File
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||
|
||
# Source common library if available
|
||
if [ -f "$SCRIPT_DIR/lib/common.sh" ]; then
|
||
source "$SCRIPT_DIR/lib/common.sh"
|
||
else
|
||
log() { echo "[INFO] $1"; }
|
||
log_error() { echo "[ERROR] $1" >&2; }
|
||
log_warn() { echo "[WARN] $1"; }
|
||
fi
|
||
|
||
log "=== K3s集群幂等性测试 ==="
|
||
echo ""
|
||
|
||
# Test counters
|
||
TOTAL_TESTS=0
|
||
PASSED_TESTS=0
|
||
FAILED_TESTS=0
|
||
|
||
# Test function
|
||
test_case() {
|
||
local name="$1"
|
||
local description="$2"
|
||
|
||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "测试 #$TOTAL_TESTS: $name"
|
||
echo "=========================================="
|
||
echo "描述: $description"
|
||
echo ""
|
||
}
|
||
|
||
test_pass() {
|
||
PASSED_TESTS=$((PASSED_TESTS + 1))
|
||
log "✓ 测试通过"
|
||
}
|
||
|
||
test_fail() {
|
||
local reason="$1"
|
||
FAILED_TESTS=$((FAILED_TESTS + 1))
|
||
log_error "✗ 测试失败: $reason"
|
||
}
|
||
|
||
# Capture initial state
|
||
capture_state() {
|
||
local state_file="$1"
|
||
|
||
log "捕获系统状态..."
|
||
|
||
{
|
||
echo "=== Nodes ==="
|
||
kubectl get nodes -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== Namespaces ==="
|
||
kubectl get namespaces -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== Deployments ==="
|
||
kubectl get deployments -A -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== Services ==="
|
||
kubectl get services -A -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== ConfigMaps ==="
|
||
kubectl get configmaps -A -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== Secrets (names only) ==="
|
||
kubectl get secrets -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== PVCs ==="
|
||
kubectl get pvc -A -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== Ingresses ==="
|
||
kubectl get ingress -A -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== ClusterIssuers ==="
|
||
kubectl get clusterissuer -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== Certificates ==="
|
||
kubectl get certificate -A -o yaml 2>/dev/null || echo "N/A"
|
||
|
||
echo "=== ArgoCD Applications ==="
|
||
kubectl get application -n argocd -o yaml 2>/dev/null || echo "N/A"
|
||
} > "$state_file"
|
||
|
||
log "✓ 状态已保存到: $state_file"
|
||
}
|
||
|
||
# Compare states
|
||
compare_states() {
|
||
local before="$1"
|
||
local after="$2"
|
||
|
||
log "比较部署前后状态..."
|
||
|
||
if diff -u "$before" "$after" > /dev/null 2>&1; then
|
||
log "✓ 状态完全一致(幂等性验证通过)"
|
||
return 0
|
||
else
|
||
log_warn "状态存在差异,检查差异详情..."
|
||
|
||
# Check for acceptable differences (timestamps, resourceVersion, etc.)
|
||
local significant_diff=false
|
||
|
||
# Filter out expected differences
|
||
diff -u "$before" "$after" | grep -v "resourceVersion" | \
|
||
grep -v "creationTimestamp" | \
|
||
grep -v "generation:" | \
|
||
grep -v "uid:" | \
|
||
grep -v "selfLink" | \
|
||
grep -v "lastTransitionTime" | \
|
||
grep -v "observedGeneration" > /tmp/filtered_diff.txt || true
|
||
|
||
if [ -s /tmp/filtered_diff.txt ]; then
|
||
log_warn "发现显著差异:"
|
||
head -50 /tmp/filtered_diff.txt
|
||
significant_diff=true
|
||
fi
|
||
|
||
rm -f /tmp/filtered_diff.txt
|
||
|
||
if [ "$significant_diff" = true ]; then
|
||
return 1
|
||
else
|
||
log "✓ 仅存在预期的元数据差异(幂等性验证通过)"
|
||
return 0
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Main test flow
|
||
main() {
|
||
log "开始幂等性测试"
|
||
log "此测试将验证部署脚本的幂等性"
|
||
echo ""
|
||
|
||
# Check if cluster is accessible
|
||
if ! kubectl cluster-info &>/dev/null; then
|
||
log_error "无法连接到K3s集群,请先部署集群"
|
||
exit 1
|
||
fi
|
||
|
||
# Test 1: Capture initial state
|
||
test_case "初始状态捕获" "捕获当前集群状态作为基准"
|
||
|
||
STATE_BEFORE="/tmp/k3s-state-before-$$.yaml"
|
||
capture_state "$STATE_BEFORE"
|
||
test_pass
|
||
|
||
# Test 2: Run deploy-all.sh
|
||
test_case "重复执行部署脚本" "运行deploy-all.sh验证幂等性"
|
||
|
||
log "执行部署脚本..."
|
||
if bash "$SCRIPT_DIR/deploy-all.sh"; then
|
||
log "✓ 部署脚本执行成功"
|
||
test_pass
|
||
else
|
||
log_error "部署脚本执行失败"
|
||
test_fail "deploy-all.sh执行失败"
|
||
fi
|
||
|
||
# Test 3: Capture state after redeployment
|
||
test_case "重新部署后状态捕获" "捕获重新部署后的集群状态"
|
||
|
||
STATE_AFTER="/tmp/k3s-state-after-$$.yaml"
|
||
capture_state "$STATE_AFTER"
|
||
test_pass
|
||
|
||
# Test 4: Compare states
|
||
test_case "状态一致性验证" "比较部署前后状态,验证幂等性"
|
||
|
||
if compare_states "$STATE_BEFORE" "$STATE_AFTER"; then
|
||
test_pass
|
||
else
|
||
test_fail "部署前后状态存在显著差异"
|
||
fi
|
||
|
||
# Test 5: Verify all services are still healthy
|
||
test_case "服务健康检查" "验证所有服务仍然正常运行"
|
||
|
||
log "运行验证脚本..."
|
||
if bash "$SCRIPT_DIR/verify-deployment.sh" > /tmp/verify-output.txt 2>&1; then
|
||
log "✓ 所有服务健康"
|
||
test_pass
|
||
else
|
||
log_error "服务验证失败"
|
||
cat /tmp/verify-output.txt
|
||
test_fail "服务健康检查失败"
|
||
fi
|
||
|
||
# Test 6: Test individual script idempotency
|
||
test_case "单个脚本幂等性" "测试各个部署脚本的幂等性"
|
||
|
||
local scripts=(
|
||
"deploy-argocd.sh"
|
||
"deploy-gitea.sh"
|
||
"deploy-https.sh"
|
||
)
|
||
|
||
local script_tests_passed=0
|
||
local script_tests_total=0
|
||
|
||
for script in "${scripts[@]}"; do
|
||
if [ -f "$SCRIPT_DIR/$script" ]; then
|
||
script_tests_total=$((script_tests_total + 1))
|
||
log "测试脚本: $script"
|
||
|
||
if bash "$SCRIPT_DIR/$script" > /tmp/script-test-$$.log 2>&1; then
|
||
log " ✓ $script 执行成功"
|
||
script_tests_passed=$((script_tests_passed + 1))
|
||
else
|
||
log_warn " ✗ $script 执行失败"
|
||
tail -20 /tmp/script-test-$$.log
|
||
fi
|
||
fi
|
||
done
|
||
|
||
if [ $script_tests_passed -eq $script_tests_total ]; then
|
||
test_pass
|
||
else
|
||
test_fail "$script_tests_passed/$script_tests_total 脚本通过测试"
|
||
fi
|
||
|
||
# Cleanup
|
||
log "清理临时文件..."
|
||
rm -f "$STATE_BEFORE" "$STATE_AFTER" /tmp/verify-output.txt /tmp/script-test-$$.log
|
||
|
||
# Print summary
|
||
echo ""
|
||
echo "=========================================="
|
||
echo " 幂等性测试总结"
|
||
echo "=========================================="
|
||
echo ""
|
||
echo "总测试数: $TOTAL_TESTS"
|
||
echo "通过: $PASSED_TESTS ✓"
|
||
echo "失败: $FAILED_TESTS ✗"
|
||
echo ""
|
||
|
||
if [ $FAILED_TESTS -eq 0 ]; then
|
||
log "✓ 所有幂等性测试通过!"
|
||
echo ""
|
||
echo "结论: 部署脚本完全支持幂等性,可以安全地重复执行。"
|
||
echo ""
|
||
exit 0
|
||
else
|
||
log_error "存在 $FAILED_TESTS 个失败的测试"
|
||
echo ""
|
||
echo "结论: 部署脚本的幂等性存在问题,需要修复。"
|
||
echo ""
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Handle script arguments
|
||
case "${1:-}" in
|
||
--help|-h)
|
||
echo "用法: $0 [选项]"
|
||
echo ""
|
||
echo "此脚本测试K3s部署的幂等性,验证脚本可以安全地重复执行。"
|
||
echo ""
|
||
echo "测试内容:"
|
||
echo " 1. 捕获初始集群状态"
|
||
echo " 2. 重复执行部署脚本"
|
||
echo " 3. 比较部署前后状态"
|
||
echo " 4. 验证服务健康"
|
||
echo " 5. 测试单个脚本幂等性"
|
||
echo ""
|
||
echo "选项:"
|
||
echo " --help 显示此帮助信息"
|
||
echo ""
|
||
exit 0
|
||
;;
|
||
esac
|
||
|
||
# Run main function
|
||
main
|