#!/usr/bin/env bash
# scripts/dns-passthrough-inflight.sh — 작업D D-2: passthrough(TCP) in-flight 스트림 + DNS flip.
#
# /slow(40s 스트림) 도중 gslb-pt.lab.internal 의 DNS를 pod-A -> pod-B 로 flip 했을 때, STRICT_DNS의
# "host 제거 시 drain"이 raw TCP 연결에도 적용되는지 4점 스냅샷(dns-inflight-4snap.sh 방식)으로 확인.
# 예상: 적용 안 됨 — tcp_proxy는 connection pool 개념이 없어 이미 맺은 연결을 CDS/EDS 갱신과 무관하게
# 그대로 들고 있을 것(HTTP의 "적극적 drain 유예"와는 다른 이유로 같은 결과가 나올 것으로 예상).
#
# 전제: scripts/dns-passthrough-churn.sh 와 동일(48 SE 적용, lab-dns zone 갱신, gslb-pt는 pod IP 타깃).
#
# 출처: docs/test-reports/2026-07-09_134250_dns-passthrough-tcp.md §5
#
# usage: bash scripts/dns-passthrough-inflight.sh
set -uo pipefail
CTX="${CTX:-homelab}"; NS="${NS:-dns-lab}"
DIR="$(cd "$(dirname "$0")/.." && pwd)"
WORK="$DIR/tmp/dns-passthrough/d2"; mkdir -p "$WORK"

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}')
# backend-a Service ClusterIP -- needed below only to re-assert the gslb.lab.internal line
# every time we touch /hosts/addn (see bug note next to the writes).
IP_A_SVC=$(kubectl --context="$CTX" -n "$NS" get svc backend-a -o jsonpath='{.spec.clusterIP}')
echo "POD_A(current gslb-pt target)=$POD_A  POD_B(flip target)=$POD_B  IP_A_SVC(gslb.lab.internal)=$IP_A_SVC"

snap(){ # $1 = label
  echo "=== $1 @ $(date +%H:%M:%S) ==="
  echo "-- dig gslb-pt --"
  kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- dig +short gslb-pt.lab.internal 2>/dev/null
  echo "-- endpoints (netshoot, gslb-pt cluster) --"
  istioctl --context="$CTX" proxy-config endpoints "deploy/netshoot.$NS" --cluster "outbound|443||gslb-pt.lab.internal" 2>/dev/null
  echo "-- cluster stats (gslb-pt, netshoot sidecar) --"
  kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -c istio-proxy -- pilot-agent request GET "stats?filter=gslb-pt" 2>/dev/null \
    | grep -E 'upstream_cx_total|upstream_cx_active|upstream_cx_destroy|membership_change|downstream_cx_total'
  echo
}

sleep_until(){ local now; now=$(date +%s); local d=$(( $1 - now )); [ "$d" -gt 0 ] && sleep "$d"; }

{
echo "# D-2 passthrough in-flight + flip — $(date +%Y-%m-%d_%H%M%S)"
echo

snap BEFORE

T0=$(date +%s)
echo "CURL_LAUNCH=$(date +%H:%M:%S) (T0=$T0) -- https://gslb-pt.lab.internal/slow, -k (SNI passthrough, cert CN mismatch expected)"
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- sh -c \
  'curl -sk -m 90 -o /tmp/ptX.bin -w "CURL_EXIT=%{exitcode} SIZE=%{size_download} TIME=%{time_total} HTTPCODE=%{http_code}" https://gslb-pt.lab.internal/slow; echo' \
  > "$WORK/curl_out.txt" 2>"$WORK/curl_stderr.txt" &
CURLPID=$!

sleep_until $((T0+5))
echo "FLIP_ISSUED=$(date +%H:%M:%S) (t=+$(( $(date +%s) - T0 ))s) gslb-pt: $POD_A -> $POD_B"
# BUG FIX (found in F-0, 2026-07-09): this used to be
#   printf '%s gslb-pt.lab.internal\n' '$POD_B' > /hosts/addn
# which OVERWRITES the whole file. /hosts/addn is shared with gslb.lab.internal (the
# HTTP-path lab host) -- the first flip call wiped that line out from under it, so the
# HTTP sanity check started failing (curl exit 6, "Could not resolve host") with no
# obvious connection to this script. Fix: always re-assert both lines together, same
# pattern already used by dns-passthrough-churn.sh / dns-passthrough-outlier.sh.
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' '$POD_B' > /hosts/addn"
echo "FLIP_DONE=$(date +%H:%M:%S) (t=+$(( $(date +%s) - T0 ))s)"
echo

sleep_until $((T0+12))
echo "[t=+$(( $(date +%s) - T0 ))s]"; snap MID1

sleep_until $((T0+30))
echo "[t=+$(( $(date +%s) - T0 ))s]"; snap MID2

wait $CURLPID
CURL_END=$(date +%s)
echo "CURL_WAIT_DONE=$(date +%H:%M:%S) (t=+$(( CURL_END - T0 ))s)"
echo "-- curl result --"
cat "$WORK/curl_out.txt"
echo "-- curl stderr --"
cat "$WORK/curl_stderr.txt"
echo

sleep 3
echo "[t=+$(( $(date +%s) - T0 ))s]"; snap AFTER

echo "-- received file check (netshoot) --"
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- sh -c 'wc -c /tmp/ptX.bin; head -c 15 /tmp/ptX.bin; echo'

echo
echo "## 복구: gslb-pt -> backend-a 현재 pod IP로 재원복"
# 위와 동일한 이유로 gslb.lab.internal 줄을 함께 재기록 (덮어쓰기 아님).
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' '$POD_A' > /hosts/addn"
sleep 6
kubectl --context="$CTX" -n "$NS" exec deploy/netshoot -- dig +short gslb-pt.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-2 raw log: $WORK/full_run.txt"
