#!/usr/bin/env bash
# scripts/dns-passthrough-churn.sh — 작업D D-1: dead-IP churn 대조, passthrough(TCP) vs 기존 HTTP 경로.
#
# 전제:
#   - scripts/dns-lab-setup.sh 로 랩이 떠 있고, 40-serviceentry-strict.yaml + 42 + 43 (HTTP 경로)
#     이 적용된 상태.
#   - scenarios/50-dns-resolution/48-serviceentry-passthrough.yaml 적용됨(gslb-pt.lab.internal SE).
#   - 10-lab-dns.yaml 의 Corefile 이 gslb-pt.lab.internal 을 hosts zone 에 포함하도록 갱신되고
#     lab-dns 가 재시작된 상태(Corefile 자체 변경은 hot-reload 안 됨 — 10-lab-dns.yaml 주석 참조).
#   - gslb-pt.lab.internal 의 DNS 타깃은 반드시 backend pod IP(Service ClusterIP 아님) 여야
#     SNI passthrough 가 실제로 작동한다 — 48-serviceentry-passthrough.yaml 의 "실측 함정" 주석
#     참조(Service VIP 로 주면 그 VIP 전용 리스너가 SNI 캐치올보다 먼저 가로챈다).
#
# 하는 일: 두 도메인 모두에 flip_both(A,B 둘 다 등록) 후 backend-a scale 0 으로 dead-IP 조건을
# 만들고, 같은 40초 창에서 passthrough curl 루프와 HTTP curl 루프를 동시(백그라운드) 실행해
# 실패율을 대조한다. 타이밍이 중요한 시퀀스이므로 전체를 단일 스크립트로 순차 실행한다.
#
# 출처: docs/test-reports/2026-07-09_134250_dns-passthrough-tcp.md §3
#
# usage: bash scripts/dns-passthrough-churn.sh
set -uo pipefail
CTX="${CTX:-homelab}"; NS="${NS:-dns-lab}"
DIR="$(cd "$(dirname "$0")/.." && pwd)"
WORK="$DIR/tmp/dns-passthrough/d1"; mkdir -p "$WORK"

IP_A_SVC=$(kubectl --context="$CTX" -n "$NS" get svc backend-a -o jsonpath='{.spec.clusterIP}')
IP_B_SVC=$(kubectl --context="$CTX" -n "$NS" get svc backend-b -o jsonpath='{.spec.clusterIP}')
POD_A=$(kubectl --context="$CTX" -n "$NS" get pods -l app=backend-a -o jsonpath='{.items[0].status.podIP}')
POD_B=$(kubectl --context="$CTX" -n "$NS" get pods -l app=backend-b -o jsonpath='{.items[0].status.podIP}')
echo "IP_A_SVC=$IP_A_SVC IP_B_SVC=$IP_B_SVC POD_A=$POD_A POD_B=$POD_B"

snap(){ # $1=label
  echo "=== $1 @ $(date +%H:%M:%S) ==="
  echo "-- dig --"
  kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- sh -c "dig +short gslb.lab.internal; echo ---; dig +short gslb-pt.lab.internal"
  echo "-- gslb.lab.internal (HTTP path) cluster stats --"
  kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -c istio-proxy -- pilot-agent request GET "stats?filter=gslb.lab.internal" 2>/dev/null \
    | grep -E 'upstream_cx_total|upstream_cx_connect_fail|upstream_cx_destroy|upstream_rq_total|upstream_rq_retry|upstream_rq_pending_failure_eject|membership_change' \
    | grep -v '^tcp\.'
  echo "-- gslb-pt.lab.internal (passthrough) cluster stats --"
  kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -c istio-proxy -- pilot-agent request GET "stats?filter=gslb-pt" 2>/dev/null
  echo
}

loop_passthrough(){ # $1=sec $2=outfile -- 각 curl=새 TCP/TLS 연결(자연 churn)
  kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- sh -c '
    end=$(( $(date +%s) + '"$1"' ))
    n=0
    while [ $(date +%s) -lt $end ]; do
      n=$((n+1))
      out=$(curl -sk --connect-timeout 3 -m 10 -o /dev/null -w "%{exitcode} %{http_code} %{time_total}" https://gslb-pt.lab.internal/ 2>&1)
      printf "%s n=%d %s\n" "$(date +%H:%M:%S)" "$n" "$out"
    done' | tee "$2"
}

loop_http(){ # $1=sec $2=outfile -- 기존 HTTP 경로(DR43 그대로, churn DR 미적용 — §3-3 참조)
  kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- sh -c '
    end=$(( $(date +%s) + '"$1"' ))
    n=0
    while [ $(date +%s) -lt $end ]; do
      n=$((n+1))
      out=$(curl -s --connect-timeout 3 -m 10 -o /dev/null -w "%{exitcode} %{http_code} %{time_total}" http://gslb.lab.internal/ 2>&1)
      printf "%s n=%d %s\n" "$(date +%H:%M:%S)" "$n" "$out"
    done' | tee "$2"
}

{
echo "# D-1 dead-IP churn: passthrough(TCP) vs HTTP 경로 대조 — $(date +%Y-%m-%d_%H%M%S)"
echo

echo "## 1. dead-IP 조건 구성"
echo "flip_both: gslb.lab.internal -> {A_SVC,B_SVC} (기존 방식 그대로), gslb-pt.lab.internal -> {POD_A,POD_B} (passthrough는 pod IP 필수)"
kubectl --context="$CTX" -n "$NS" exec deploy/lab-dns -c writer -- sh -c \
  "printf '%s gslb.lab.internal\n%s gslb.lab.internal\n%s gslb-pt.lab.internal\n%s gslb-pt.lab.internal\n' '$IP_A_SVC' '$IP_B_SVC' '$POD_A' '$POD_B' > /hosts/addn; cat /hosts/addn"
sleep 6
echo "-- pre-kill dig (both A,B 등록 확인) --"
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- sh -c 'dig +short gslb.lab.internal; echo ---; dig +short gslb-pt.lab.internal'

echo
echo ">> KILL backend-a (scale 0) @ $(date +%H:%M:%S) — Service ClusterIP=dead(0 endpoint), pod IP=dead(라우트 제거)"
kubectl --context="$CTX" -n "$NS" scale deploy/backend-a --replicas=0
sleep 4

echo
echo "## 2. BEFORE snapshot"
snap BEFORE | tee "$WORK/before.txt"

echo
echo "## 3. LOAD 40s (passthrough, HTTP 두 루프 동시 백그라운드 실행)"
echo "start=$(date +%H:%M:%S)"
loop_passthrough 40 "$WORK/loop_pt.txt" > /dev/null 2>&1 &
PPID_PT=$!
loop_http 40 "$WORK/loop_http.txt" > /dev/null 2>&1 &
PPID_HTTP=$!
wait $PPID_PT 2>/dev/null
wait $PPID_HTTP 2>/dev/null
echo "end=$(date +%H:%M:%S)"

echo
echo "## 4. AFTER snapshot"
snap AFTER | tee "$WORK/after.txt"

echo
echo "## 5. upstream_rq_* 존재 여부 확인 (passthrough cluster, AFTER 시점)"
echo '```'
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -c istio-proxy -- pilot-agent request GET "stats?filter=gslb-pt" 2>/dev/null | grep -c 'upstream_rq' | xargs -I{} echo "upstream_rq_* count for gslb-pt cluster = {}"
echo '```'

echo
echo "## 6. 요청 결과 집계"
echo "### passthrough loop 원시 (마지막 5줄 + 통계)"
echo '```'
tail -5 "$WORK/loop_pt.txt"
echo "총시도: $(wc -l < "$WORK/loop_pt.txt")"
echo "exitcode=0(성공) 건수: $(awk '{print $3}' "$WORK/loop_pt.txt" | grep -c '^0$')"
echo "exitcode!=0 건수 및 분포:"; awk '{print $3}' "$WORK/loop_pt.txt" | grep -v '^0$' | sort | uniq -c
echo '```'
echo "### HTTP loop 원시 (마지막 5줄 + 통계)"
echo '```'
tail -5 "$WORK/loop_http.txt"
echo "총시도: $(wc -l < "$WORK/loop_http.txt")"
echo "exitcode=0(성공) 건수: $(awk '{print $3}' "$WORK/loop_http.txt" | grep -c '^0$')"
echo "http_code!=200 건수: $(awk '{print $4}' "$WORK/loop_http.txt" | grep -vc '^200$')"
echo '```'

echo
echo "## 7. 복구"
kubectl --context="$CTX" -n "$NS" scale deploy/backend-a --replicas=1
kubectl --context="$CTX" -n "$NS" rollout status deploy/backend-a --timeout=90s
sleep 3
NEW_POD_A=$(kubectl --context="$CTX" -n "$NS" get pods -l app=backend-a -o jsonpath='{.items[0].status.podIP}')
echo "new backend-a pod IP = $NEW_POD_A"
kubectl --context="$CTX" -n "$NS" exec deploy/lab-dns -c writer -- sh -c \
  "printf '%s gslb.lab.internal\n%s gslb-pt.lab.internal\n' '$IP_A_SVC' '$NEW_POD_A' > /hosts/addn; cat /hosts/addn"
sleep 6
echo "-- post-restore sanity --"
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- sh -c 'dig +short gslb.lab.internal; echo ---; dig +short gslb-pt.lab.internal'
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- curl -s -m 5 -w " [http_code=%{http_code}]\n" http://gslb.lab.internal/
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- curl -sk -m 5 -w " [http_code=%{http_code}]\n" https://gslb-pt.lab.internal/
} 2>&1 | tee "$WORK/full_run.txt"

echo ">> D-1 raw log: $WORK/full_run.txt"
