#!/bin/bash # ============================================================================= # Docker Registry CI/CD 驗證腳本 # 用途: 驗證新的 Registry-based CI/CD 流程是否正常運作 # ============================================================================= set -e # 顏色 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # 配置 REGISTRY_URL="registry.wooo.work" REGISTRY_LOCAL_URL="http://127.0.0.1:5000" UAT_HOST="192.168.0.110" UAT_USER="wooo" GCP_HOST="35.194.233.141" GCP_USER="wooo" # 計數器 PASSED=0 FAILED=0 WARNINGS=0 # ============================================================================= # 輸出函數 # ============================================================================= log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASSED++)); } log_fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAILED++)); } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; ((WARNINGS++)); } section() { echo "" echo "==============================================" echo -e "${BLUE}$1${NC}" echo "==============================================" } # ============================================================================= # 1. 本地環境檢查 # ============================================================================= check_local_env() { section "1. 本地環境檢查" # Docker if command -v docker &> /dev/null; then log_pass "Docker 已安裝: $(docker --version | cut -d' ' -f3)" else log_fail "Docker 未安裝" fi # Git if command -v git &> /dev/null; then log_pass "Git 已安裝: $(git --version | cut -d' ' -f3)" else log_fail "Git 未安裝" fi # SSH if command -v ssh &> /dev/null; then log_pass "SSH 已安裝" else log_fail "SSH 未安裝" fi # curl if command -v curl &> /dev/null; then log_pass "curl 已安裝" else log_fail "curl 未安裝" fi } # ============================================================================= # 2. SSH 連線檢查 # ============================================================================= check_ssh_connections() { section "2. SSH 連線檢查" # UAT if ssh -o BatchMode=yes -o ConnectTimeout=5 ${UAT_USER}@${UAT_HOST} "echo 'ok'" &> /dev/null; then log_pass "UAT SSH 連線正常 (${UAT_HOST})" else log_fail "UAT SSH 連線失敗 (${UAT_HOST})" fi # GCP if ssh -o BatchMode=yes -o ConnectTimeout=5 ${GCP_USER}@${GCP_HOST} "echo 'ok'" &> /dev/null; then log_pass "GCP SSH 連線正常 (${GCP_HOST})" else log_warn "GCP SSH 連線失敗 (${GCP_HOST}) - 可能需要設定 SSH Key" fi } # ============================================================================= # 3. Registry 服務檢查 # ============================================================================= check_registry_service() { section "3. Registry 服務檢查" # 本地連線測試 (透過 SSH 到 UAT) log_info "檢查 Registry 本地連線 (127.0.0.1:5000)..." local local_status=$(ssh ${UAT_USER}@${UAT_HOST} "curl -s -o /dev/null -w '%{http_code}' ${REGISTRY_LOCAL_URL}/v2/ --max-time 10" 2>/dev/null || echo "000") if [[ "$local_status" == "200" ]]; then log_pass "Registry 本地連線正常 (HTTP $local_status)" else log_fail "Registry 本地連線失敗 (HTTP $local_status)" fi # 外部 HTTPS 連線測試 log_info "檢查 Registry 外部連線 (https://${REGISTRY_URL})..." local external_status=$(curl -s -o /dev/null -w "%{http_code}" "https://${REGISTRY_URL}/v2/" --max-time 10 2>/dev/null || echo "000") if [[ "$external_status" == "401" ]]; then log_pass "Registry 外部連線正常 (需要認證, HTTP 401)" elif [[ "$external_status" == "200" ]]; then log_pass "Registry 外部連線正常 (HTTP 200)" else log_fail "Registry 外部連線失敗 (HTTP $external_status)" fi # Docker 登入測試 (如果有認證資訊) if [[ -n "$REGISTRY_USER" && -n "$REGISTRY_PASSWORD" ]]; then log_info "測試 Docker 登入..." if echo "$REGISTRY_PASSWORD" | docker login "$REGISTRY_URL" -u "$REGISTRY_USER" --password-stdin &> /dev/null; then log_pass "Docker 登入成功" docker logout "$REGISTRY_URL" &> /dev/null else log_fail "Docker 登入失敗" fi else log_warn "未設定 REGISTRY_USER/REGISTRY_PASSWORD,跳過登入測試" fi } # ============================================================================= # 4. K8s 服務狀態檢查 # ============================================================================= check_k8s_services() { section "4. K8s 服務狀態檢查 (UAT)" # 檢查 Pod 狀態 log_info "檢查 K8s Pod 狀態..." local pods=$(ssh ${UAT_USER}@${UAT_HOST} "kubectl get pods -n momo -o wide 2>/dev/null" || echo "error") if [[ "$pods" == "error" ]]; then log_fail "無法取得 K8s Pod 狀態" return fi echo "$pods" echo "" # momo-app if echo "$pods" | grep -q "momo-app.*Running"; then log_pass "momo-app Pod 運行中" else log_fail "momo-app Pod 異常" fi # momo-scheduler if echo "$pods" | grep -q "momo-scheduler.*Running"; then log_pass "momo-scheduler Pod 運行中" else log_fail "momo-scheduler Pod 異常" fi # momo-postgres if echo "$pods" | grep -q "momo-postgres.*Running"; then log_pass "momo-postgres Pod 運行中" else log_fail "momo-postgres Pod 異常" fi # 檢查 Registry Secret log_info "檢查 Registry Secret..." if ssh ${UAT_USER}@${UAT_HOST} "kubectl get secret registry-secret -n momo &>/dev/null"; then log_pass "registry-secret 已建立" else log_warn "registry-secret 不存在,需要建立" fi } # ============================================================================= # 5. 應用健康檢查 # ============================================================================= check_app_health() { section "5. 應用健康檢查" # UAT log_info "檢查 UAT 應用 (https://mo.wooo.work)..." local uat_health=$(curl -s "https://mo.wooo.work/health" --max-time 10 2>/dev/null || echo "error") if echo "$uat_health" | grep -q "healthy"; then log_pass "UAT 應用健康檢查通過" else log_fail "UAT 應用健康檢查失敗" fi # GCP log_info "檢查 GCP 應用 (https://momo.wooo.work)..." local gcp_health=$(curl -s "https://momo.wooo.work/health" --max-time 10 2>/dev/null || echo "error") if echo "$gcp_health" | grep -q "healthy"; then log_pass "GCP 應用健康檢查通過" else log_warn "GCP 應用健康檢查失敗 (可能尚未部署)" fi } # ============================================================================= # 6. CI/CD 配置檢查 # ============================================================================= check_cicd_config() { section "6. CI/CD 配置檢查" # .gitlab-ci.yml if [[ -f ".gitlab-ci.yml" ]]; then log_pass ".gitlab-ci.yml 存在" # 檢查 Registry URL if grep -q "REGISTRY_URL.*registry.wooo.work" .gitlab-ci.yml; then log_pass "REGISTRY_URL 配置正確" else log_fail "REGISTRY_URL 配置錯誤或缺失" fi # 檢查是否還有 Harbor 引用 if grep -qi "harbor" .gitlab-ci.yml; then log_fail "仍有 Harbor 引用存在於 .gitlab-ci.yml" else log_pass "無 Harbor 引用" fi else log_fail ".gitlab-ci.yml 不存在" fi # K8s 配置 for file in "k8s/04-momo-app.yaml" "k8s/05-scheduler.yaml"; do if [[ -f "$file" ]]; then if grep -q "registry.wooo.work" "$file"; then log_pass "$file 使用正確的 Registry" else log_fail "$file 未使用 registry.wooo.work" fi if grep -qi "harbor" "$file"; then log_fail "$file 仍有 Harbor 引用" fi else log_warn "$file 不存在" fi done # docker-compose.yml if [[ -f "docker-compose.yml" ]]; then if grep -qi "harbor" docker-compose.yml; then log_fail "docker-compose.yml 仍有 Harbor 引用" else log_pass "docker-compose.yml 無 Harbor 引用" fi fi } # ============================================================================= # 7. Registry 映像檢查 # ============================================================================= check_registry_images() { section "7. Registry 映像檢查" if [[ -z "$REGISTRY_USER" || -z "$REGISTRY_PASSWORD" ]]; then log_warn "未設定認證資訊,跳過映像檢查" return fi log_info "列出 Registry 中的映像..." local catalog=$(curl -s -u "${REGISTRY_USER}:${REGISTRY_PASSWORD}" \ "https://${REGISTRY_URL}/v2/_catalog" --max-time 10 2>/dev/null) if echo "$catalog" | grep -q "repositories"; then log_pass "可以存取 Registry catalog" echo "$catalog" | jq . 2>/dev/null || echo "$catalog" else log_fail "無法存取 Registry catalog" fi # 檢查主映像 log_info "檢查 wooo/momo-pro-system 映像..." local tags=$(curl -s -u "${REGISTRY_USER}:${REGISTRY_PASSWORD}" \ "https://${REGISTRY_URL}/v2/wooo/momo-pro-system/tags/list" --max-time 10 2>/dev/null) if echo "$tags" | grep -q "tags"; then log_pass "wooo/momo-pro-system 映像存在" echo "$tags" | jq . 2>/dev/null || echo "$tags" else log_warn "wooo/momo-pro-system 映像尚未推送" fi } # ============================================================================= # 8. 監控腳本檢查 # ============================================================================= check_monitoring_scripts() { section "8. 監控腳本檢查" # Registry 健康監控 if [[ -f "scripts/registry_health_monitor.sh" ]]; then log_pass "Registry 健康監控腳本存在" else log_fail "Registry 健康監控腳本不存在" fi # 部署腳本庫 if [[ -f "deploy/lib/registry.sh" ]]; then log_pass "Registry 部署函數庫存在" else log_fail "Registry 部署函數庫不存在" fi # Nginx 配置 if [[ -f "config/nginx/sites-available/registry" ]]; then log_pass "Registry Nginx 配置存在" else log_warn "Registry Nginx 配置不存在" fi # Docker Compose if [[ -f "docker/registry/docker-compose.yml" ]]; then log_pass "Registry docker-compose.yml 存在" else log_fail "Registry docker-compose.yml 不存在" fi } # ============================================================================= # 9. 全域 Harbor 引用檢查 # ============================================================================= check_harbor_references() { section "9. 全域 Harbor 引用檢查" log_info "搜尋所有檔案中的 Harbor 引用..." local harbor_files=$(grep -ril "harbor" \ --include="*.py" \ --include="*.yaml" \ --include="*.yml" \ --include="*.sh" \ --include="*.html" \ --include="*.md" \ . 2>/dev/null | grep -v ".git" | grep -v "node_modules" | grep -v "__pycache__" || true) if [[ -z "$harbor_files" ]]; then log_pass "無 Harbor 引用存在" else log_warn "以下檔案仍有 Harbor 引用:" echo "$harbor_files" | while read -r file; do echo " - $file" done fi } # ============================================================================= # 總結報告 # ============================================================================= summary() { section "驗證報告總結" echo "" echo -e "✅ ${GREEN}通過${NC}: $PASSED" echo -e "❌ ${RED}失敗${NC}: $FAILED" echo -e "⚠️ ${YELLOW}警告${NC}: $WARNINGS" echo "" if [[ $FAILED -eq 0 ]]; then echo -e "${GREEN}==============================================" echo " CI/CD 驗證通過!可以進行部署。" echo "==============================================${NC}" return 0 else echo -e "${RED}==============================================" echo " CI/CD 驗證失敗!請修復上述問題。" echo "==============================================${NC}" return 1 fi } # ============================================================================= # 主程式 # ============================================================================= main() { echo "" echo "==============================================" echo " Docker Registry CI/CD 驗證" echo " $(date '+%Y-%m-%d %H:%M:%S')" echo "==============================================" check_local_env check_ssh_connections check_registry_service check_k8s_services check_app_health check_cicd_config check_registry_images check_monitoring_scripts check_harbor_references summary } # 執行 main "$@"