324 lines
9.0 KiB
Bash
324 lines
9.0 KiB
Bash
#!/usr/bin/env bash
|
||
|
||
# PAM 测试脚本(Shell 入口)。
|
||
set -uo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
# 复用部署脚本中的函数供测试脚本调用。
|
||
# shellcheck source=./deploy.sh
|
||
source "${SCRIPT_DIR}/deploy.sh"
|
||
|
||
TEST_MODE="full"
|
||
SKIP_ROLLBACK="false"
|
||
MAX_IPS=0
|
||
TEST_RESULTS=()
|
||
HAS_FAILURE=0
|
||
|
||
test_usage() {
|
||
cat <<'EOF'
|
||
用法:
|
||
./test_deploy.sh [--config /path/to/config.txt] [--mode smoke|full] [--skip-rollback] [--max-ips N]
|
||
|
||
模式:
|
||
smoke 仅测试配置、Token、Node 和在线 IP 查询
|
||
full 按部署顺序测试全部接口
|
||
|
||
说明:
|
||
- full 模式会测试建版、上传、发布、Node 下载、升级、启动、校验和日志下载
|
||
- rollback 默认会额外测试一次
|
||
- 如果不希望测试脚本改变部署状态,可加 --skip-rollback
|
||
- --max-ips 可限制参与接口测试的在线 IP 数量
|
||
EOF
|
||
}
|
||
|
||
add_test_result() {
|
||
local step="$1"
|
||
local status="$2"
|
||
local detail="$3"
|
||
|
||
TEST_RESULTS+=("${step}|${status}|${detail}")
|
||
if [[ "$status" == "FAIL" ]]; then
|
||
HAS_FAILURE=1
|
||
fi
|
||
|
||
case "$status" in
|
||
PASS)
|
||
printf '[PASS] %s | %s\n' "$step" "$detail"
|
||
;;
|
||
FAIL)
|
||
printf '[FAIL] %s | %s\n' "$step" "$detail" >&2
|
||
;;
|
||
SKIP)
|
||
printf '[SKIP] %s | %s\n' "$step" "$detail"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
print_test_report() {
|
||
local pass_count=0
|
||
local fail_count=0
|
||
local skip_count=0
|
||
|
||
for row in "${TEST_RESULTS[@]}"; do
|
||
IFS='|' read -r _step _status _detail <<< "$row"
|
||
case "$_status" in
|
||
PASS) pass_count=$((pass_count + 1)) ;;
|
||
FAIL) fail_count=$((fail_count + 1)) ;;
|
||
SKIP) skip_count=$((skip_count + 1)) ;;
|
||
esac
|
||
done
|
||
|
||
printf '\n====================== API TEST REPORT ======================\n'
|
||
printf 'PASS: %s\n' "$pass_count"
|
||
printf 'FAIL: %s\n' "$fail_count"
|
||
printf 'SKIP: %s\n\n' "$skip_count"
|
||
printf '%-28s %-8s %s\n' "STEP" "STATUS" "DETAIL"
|
||
|
||
for row in "${TEST_RESULTS[@]}"; do
|
||
IFS='|' read -r step status detail <<< "$row"
|
||
printf '%-28s %-8s %s\n' "$step" "$status" "$detail"
|
||
done
|
||
}
|
||
|
||
run_smoke_test() {
|
||
load_config "$1"
|
||
ensure_dependencies
|
||
|
||
if ensure_zip_file; then
|
||
add_test_result "ZIP_FILE" "PASS" "$ZIP_FILE_PATH"
|
||
else
|
||
add_test_result "ZIP_FILE" "FAIL" "$ZIP_FILE_PATH"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if get_token; then
|
||
add_test_result "TOKEN" "PASS" "token length=${#TOKEN}"
|
||
else
|
||
add_test_result "TOKEN" "FAIL" "token request failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if get_node_url; then
|
||
add_test_result "TARGET_NODE" "PASS" "$NODE_URL"
|
||
else
|
||
add_test_result "TARGET_NODE" "FAIL" "node lookup failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if get_online_ips; then
|
||
add_test_result "ONLINE_IPS" "PASS" "${ONLINE_IPS[*]}"
|
||
else
|
||
add_test_result "ONLINE_IPS" "FAIL" "online ip lookup failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
print_test_report
|
||
}
|
||
|
||
run_full_test() {
|
||
local config_path="$1"
|
||
local rollback_tested="false"
|
||
local -a test_ips=()
|
||
|
||
load_config "$config_path"
|
||
ensure_dependencies
|
||
|
||
if ensure_zip_file; then
|
||
add_test_result "ZIP_FILE" "PASS" "$ZIP_FILE_PATH"
|
||
else
|
||
add_test_result "ZIP_FILE" "FAIL" "$ZIP_FILE_PATH"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if get_token; then
|
||
add_test_result "TOKEN" "PASS" "token length=${#TOKEN}"
|
||
else
|
||
add_test_result "TOKEN" "FAIL" "token request failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if create_version; then
|
||
add_test_result "CREATE_VERSION" "PASS" "$VERSION_NUMBER"
|
||
else
|
||
add_test_result "CREATE_VERSION" "FAIL" "$VERSION_NUMBER"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if upload_package; then
|
||
add_test_result "UPLOAD_PACKAGE" "PASS" "$HASH_CODE"
|
||
else
|
||
add_test_result "UPLOAD_PACKAGE" "FAIL" "upload failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if publish_version; then
|
||
add_test_result "PUBLISH_VERSION" "PASS" "$AIRPORT_CODE"
|
||
else
|
||
add_test_result "PUBLISH_VERSION" "FAIL" "publish failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if get_node_url; then
|
||
add_test_result "TARGET_NODE" "PASS" "$NODE_URL"
|
||
else
|
||
add_test_result "TARGET_NODE" "FAIL" "node lookup failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if get_online_ips; then
|
||
add_test_result "ONLINE_IPS" "PASS" "${ONLINE_IPS[*]}"
|
||
else
|
||
add_test_result "ONLINE_IPS" "FAIL" "online ip lookup failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
if download_cloud_to_node; then
|
||
add_test_result "DOWNLOAD_TO_NODE" "PASS" "$VERSION_NUMBER"
|
||
else
|
||
add_test_result "DOWNLOAD_TO_NODE" "FAIL" "node download failed"
|
||
print_test_report
|
||
return 1
|
||
fi
|
||
|
||
test_ips=("${ONLINE_IPS[@]}")
|
||
if (( MAX_IPS > 0 )) && (( ${#test_ips[@]} > MAX_IPS )); then
|
||
test_ips=("${test_ips[@]:0:MAX_IPS}")
|
||
fi
|
||
|
||
for ip in "${test_ips[@]}"; do
|
||
local upgrade_response=""
|
||
local upgrade_success=""
|
||
local upgrade_message=""
|
||
local verify_response=""
|
||
local verify_success=""
|
||
local verify_message=""
|
||
local log_file=""
|
||
local rollback_result=""
|
||
|
||
if upgrade_response="$(upgrade_ip "$ip")"; then
|
||
upgrade_success="$(json_value "$upgrade_response" '.success')"
|
||
upgrade_message="$(json_value "$upgrade_response" '.message')"
|
||
if [[ "$upgrade_success" == "true" ]]; then
|
||
add_test_result "UPGRADE [$ip]" "PASS" "success=true"
|
||
else
|
||
[[ -z "$upgrade_message" ]] && upgrade_message="success != true"
|
||
add_test_result "UPGRADE [$ip]" "FAIL" "$upgrade_message"
|
||
fi
|
||
else
|
||
add_test_result "UPGRADE [$ip]" "FAIL" "request failed"
|
||
fi
|
||
|
||
if start_application "$ip"; then
|
||
add_test_result "START [$ip]" "PASS" "request completed"
|
||
else
|
||
add_test_result "START [$ip]" "FAIL" "request failed"
|
||
fi
|
||
|
||
if verify_response="$(verify_ip "$ip")"; then
|
||
verify_success="$(json_value "$verify_response" '.success')"
|
||
verify_message="$(json_value "$verify_response" '.message')"
|
||
if [[ "$verify_success" == "true" ]]; then
|
||
add_test_result "VERIFY [$ip]" "PASS" "success=true"
|
||
else
|
||
[[ -z "$verify_message" ]] && verify_message="success != true"
|
||
add_test_result "VERIFY [$ip]" "FAIL" "$verify_message"
|
||
fi
|
||
else
|
||
add_test_result "VERIFY [$ip]" "FAIL" "request failed"
|
||
fi
|
||
|
||
if log_file="$(download_log "$ip")"; then
|
||
add_test_result "LOG_DOWNLOAD [$ip]" "PASS" "$log_file"
|
||
else
|
||
add_test_result "LOG_DOWNLOAD [$ip]" "FAIL" "log download failed: ${log_file}"
|
||
fi
|
||
|
||
if [[ "$SKIP_ROLLBACK" == "false" && "$rollback_tested" == "false" ]]; then
|
||
rollback_result="$(rollback_ip "$ip" "true")"
|
||
if [[ "$rollback_result" == "ROLLBACK_SUCCESS" ]]; then
|
||
add_test_result "ROLLBACK [$ip]" "PASS" "$rollback_result"
|
||
else
|
||
add_test_result "ROLLBACK [$ip]" "FAIL" "$rollback_result"
|
||
fi
|
||
rollback_tested="true"
|
||
fi
|
||
done
|
||
|
||
if [[ "$SKIP_ROLLBACK" == "true" ]]; then
|
||
add_test_result "ROLLBACK" "SKIP" "skipped by parameter"
|
||
elif [[ "$rollback_tested" == "false" ]]; then
|
||
add_test_result "ROLLBACK" "SKIP" "no IP available for rollback test"
|
||
fi
|
||
|
||
print_test_report
|
||
|
||
if (( HAS_FAILURE != 0 )); then
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
main() {
|
||
local config_path="$DEFAULT_CONFIG_PATH"
|
||
|
||
while (($#)); do
|
||
case "$1" in
|
||
--config)
|
||
[[ $# -lt 2 ]] && { log_error "--config 缺少路径"; exit 1; }
|
||
config_path="$2"
|
||
shift 2
|
||
;;
|
||
--mode)
|
||
[[ $# -lt 2 ]] && { log_error "--mode 缺少取值"; exit 1; }
|
||
TEST_MODE="$2"
|
||
shift 2
|
||
;;
|
||
--skip-rollback)
|
||
SKIP_ROLLBACK="true"
|
||
shift
|
||
;;
|
||
--max-ips)
|
||
[[ $# -lt 2 ]] && { log_error "--max-ips 缺少取值"; exit 1; }
|
||
MAX_IPS="$2"
|
||
shift 2
|
||
;;
|
||
-h|--help)
|
||
test_usage
|
||
exit 0
|
||
;;
|
||
*)
|
||
log_error "未知参数: $1"
|
||
test_usage
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
case "$TEST_MODE" in
|
||
smoke)
|
||
run_smoke_test "$config_path"
|
||
;;
|
||
full)
|
||
run_full_test "$config_path"
|
||
;;
|
||
*)
|
||
log_error "不支持的测试模式: $TEST_MODE"
|
||
exit 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
||
main "$@"
|
||
fi
|