zioinfo-mail/itsm/cicd/scripts/pipeline/health_check.sh
DESKTOP-TKLFCPR\ython e228faabf5 feat(itsm): G-1~G-12 확장 기능 + 하네스/봇/설치스크립트 구현
G-1: 메신저 Webhook Relay + _send_to_room 실제 httpx 호출 구현
G-2: POST /api/tasks/bulk SR 대량작업 엔드포인트 (최대 100건)
G-3: 라이선스 만료 알림 스케줄러 (매일 09:00 KST)
G-4: 체험판 upgrade_banner 필드 + license.py 배너 로직
G-5: core/auto_rca.py + incidents/problem auto-rca 엔드포인트
G-6: core/deploy_impact.py + vibe impact-analysis 엔드포인트
G-7: core/ticket_classifier.py + SR 생성 시 AI 분류 + ai-suggestion API
G-8: VulnPatchRecord 모델 + vuln_scan 패치추적 4개 엔드포인트
G-9: core/jira_sync.py + gateway Jira/Confluence 연동 엔드포인트
G-10: core/push_notify.py + routers/push.py + PushSubscription 모델
G-11: approvals 다중승인 (위임/서명/기한초과/마감연장)
G-12: alembic.ini + migrations/ + cicd/migrate_to_postgres.sh

하네스: guardia-orchestrator 확장기능 Phase 반영
봇명령어: /sr /status /license /bulk 슬래시 명령어 추가
설치스크립트: setup/ (Ubuntu, CentOS, RHEL, Windows) --test 옵션 포함

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:18:52 +09:00

160 lines
5.4 KiB
Bash

#!/usr/bin/env bash
# =============================================================================
# 헬스체크 스크립트 (HTTP / TCP)
# Jenkins Stage 7: Health Check에서 호출
# 사용: health_check.sh --url <URL> [--timeout 60] [--retries 3] [--interval 10]
# =============================================================================
set -euo pipefail
CHECK_URL=""
CHECK_TYPE="http" # http | tcp
TCP_HOST=""
TCP_PORT=""
TIMEOUT="${HEALTH_TIMEOUT:-60}"
RETRIES="${HEALTH_RETRIES:-3}"
INTERVAL="${HEALTH_INTERVAL:-10}"
EXPECT_STATUS="${EXPECT_STATUS:-200}"
LOG_DIR="${WORKSPACE:-/tmp}/build-logs"
HC_LOG="${LOG_DIR}/healthcheck-$(date +%Y%m%d-%H%M%S).log"
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; NC='\033[0m'
log() { echo -e "${GREEN}[HEALTH]${NC} $*" | tee -a "${HC_LOG}"; }
err() { echo -e "${RED}[ERROR]${NC} $*" | tee -a "${HC_LOG}"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*" | tee -a "${HC_LOG}"; }
mkdir -p "${LOG_DIR}"
while [[ $# -gt 0 ]]; do
case $1 in
--url) CHECK_URL="$2"; CHECK_TYPE="http"; shift 2 ;;
--host) TCP_HOST="$2"; CHECK_TYPE="tcp"; shift 2 ;;
--port) TCP_PORT="$2"; CHECK_TYPE="tcp"; shift 2 ;;
--timeout) TIMEOUT="$2"; shift 2 ;;
--retries) RETRIES="$2"; shift 2 ;;
--interval) INTERVAL="$2"; shift 2 ;;
--expect) EXPECT_STATUS="$2";shift 2 ;;
*) shift ;;
esac
done
# ── HTTP 헬스체크 ────────────────────────────────────────────────────────────
check_http() {
log "HTTP 헬스체크: ${CHECK_URL}"
log " 예상 상태코드: ${EXPECT_STATUS}"
log " 타임아웃: ${TIMEOUT}초 / 재시도: ${RETRIES}"
local attempt=0
while [[ ${attempt} -lt ${RETRIES} ]]; do
attempt=$((attempt + 1))
log " 시도 ${attempt}/${RETRIES}..."
local http_code
local response_time_ms
local start_ns
start_ns=$(date +%s%N 2>/dev/null || echo 0)
http_code=$(curl \
--silent \
--output /dev/null \
--write-out "%{http_code}" \
--max-time "${TIMEOUT}" \
--connect-timeout 10 \
--location \
"${CHECK_URL}" 2>/dev/null || echo "000")
local end_ns
end_ns=$(date +%s%N 2>/dev/null || echo 0)
if [[ "${start_ns}" != "0" ]]; then
response_time_ms=$(( (end_ns - start_ns) / 1000000 ))
else
response_time_ms="N/A"
fi
log " 응답: HTTP ${http_code} (${response_time_ms}ms)"
if [[ "${http_code}" == "${EXPECT_STATUS}" ]]; then
log "✅ 헬스체크 통과: HTTP ${http_code}"
return 0
elif [[ "${http_code}" == "000" ]]; then
warn " 연결 실패 (타임아웃 또는 접속 거부)"
else
warn " 예상과 다른 응답: ${http_code} (예상: ${EXPECT_STATUS})"
fi
if [[ ${attempt} -lt ${RETRIES} ]]; then
log " ${INTERVAL}초 후 재시도..."
sleep "${INTERVAL}"
fi
done
err "헬스체크 실패: ${RETRIES}회 모두 실패"
return 1
}
# ── TCP 헬스체크 ────────────────────────────────────────────────────────────
check_tcp() {
[[ -z "${TCP_HOST}" ]] && { err "--host 파라미터가 필요합니다"; exit 1; }
[[ -z "${TCP_PORT}" ]] && { err "--port 파라미터가 필요합니다"; exit 1; }
log "TCP 헬스체크: ${TCP_HOST}:${TCP_PORT}"
local attempt=0
while [[ ${attempt} -lt ${RETRIES} ]]; do
attempt=$((attempt + 1))
log " 시도 ${attempt}/${RETRIES}..."
if timeout "${TIMEOUT}" bash -c \
"echo >/dev/tcp/${TCP_HOST}/${TCP_PORT}" 2>/dev/null; then
log "✅ TCP 연결 성공: ${TCP_HOST}:${TCP_PORT}"
return 0
fi
warn " TCP 연결 실패: ${TCP_HOST}:${TCP_PORT}"
if [[ ${attempt} -lt ${RETRIES} ]]; then
log " ${INTERVAL}초 후 재시도..."
sleep "${INTERVAL}"
fi
done
err "TCP 헬스체크 실패: ${RETRIES}회 모두 실패"
return 1
}
# ── 복합 헬스체크 ─────────────────────────────────────────────────────────────
check_composite() {
# HTTP + 추가 TCP 포트 확인
check_http || return 1
if [[ -n "${TCP_HOST}" ]] && [[ -n "${TCP_PORT}" ]]; then
check_tcp || return 1
fi
return 0
}
# ── 메인 ─────────────────────────────────────────────────────────────────────
main() {
log "=== 헬스체크 시작: $(date) ==="
case "${CHECK_TYPE}" in
http)
[[ -z "${CHECK_URL}" ]] && { err "--url 파라미터가 필요합니다"; exit 1; }
check_http
;;
tcp)
check_tcp
;;
composite)
check_composite
;;
*)
err "알 수 없는 헬스체크 유형: ${CHECK_TYPE}"
exit 1
;;
esac
log "=== 헬스체크 통과 ==="
}
main "$@"