#!/usr/bin/env bash
set -uo pipefail
OUT="k8s_container_time_timezone_report_$(date +%Y%m%d_%H%M%S).txt"; NS=""; CTX=""; PARALLEL=10; LIMIT=15
usage(){ echo "用法: $0 [-n namespace] [-o report.txt] [-c context] [-p parallel] [-t timeout]"; }
while getopts ':n:o:c:p:t:h' o; do case "$o" in n) NS="$OPTARG";;o) OUT="$OPTARG";;c) CTX="$OPTARG";;p) PARALLEL="$OPTARG";;t) LIMIT="$OPTARG";;h) usage;exit 0;;:) echo "选项 -$OPTARG 缺少参数" >&2;exit 2;;\?) echo "未知选项 -$OPTARG" >&2;exit 2;;esac; done
[[ "$PARALLEL" =~ ^[1-9][0-9]*$ && "$LIMIT" =~ ^[1-9][0-9]*$ ]] || { echo "-p/-t 必须为正整数" >&2; exit 2; }
for x in kubectl jq timeout; do command -v "$x" >/dev/null 2>&1 || { echo "缺少依赖：$x" >&2; exit 1; }; done
kc(){ if [[ -n "$CTX" && -n "$NS" ]];then command kubectl --context "$CTX" -n "$NS" "$@";elif [[ -n "$CTX" ]];then command kubectl --context "$CTX" "$@";elif [[ -n "$NS" ]];then command kubectl -n "$NS" "$@";else command kubectl "$@";fi; }
kx(){ if [[ -n "$CTX" && -n "$NS" ]];then timeout "$LIMIT" kubectl --context "$CTX" -n "$NS" "$@";elif [[ -n "$CTX" ]];then timeout "$LIMIT" kubectl --context "$CTX" "$@";elif [[ -n "$NS" ]];then timeout "$LIMIT" kubectl -n "$NS" "$@";else timeout "$LIMIT" kubectl "$@";fi; }
kc version --request-timeout=10s -o json >/dev/null 2>&1 || { echo "无法连接 Kubernetes 集群" >&2; exit 1; }
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
RS="$(kc get rs -o json 2>/dev/null)"; PODS="$(kc get pods -o json 2>/dev/null)"; [[ -n "$PODS" ]] || { echo "无法读取 Pod 列表" >&2;exit 1; }
declare -A RS_DEP=()
while IFS=$'\t' read -r n r d; do [[ -n "${n:-}" ]] && RS_DEP["$n/$r"]="$d"; done < <(jq -r '.items[]|(.metadata.ownerReferences//[]|map(select(.controller==true and .kind=="Deployment"))|.[0].name//"") as $d|select($d!="")|[.metadata.namespace,.metadata.name,$d]|@tsv' <<< "$RS")
declare -A GN=() GL=() GP=() GH=() GC=() GS=()
while IFS=$'\t' read -r n pod phase ready kind owner containers; do
  [[ -n "${n:-}" ]] || continue; label='<orphan>'
  if [[ "${kind:-}" != '-' && -n "${owner:-}" ]];then if [[ "$kind" == ReplicaSet && -n "${RS_DEP[$n/$owner]:-}" ]];then label="${RS_DEP[$n/$owner]}";else label="<$kind:$owner>";fi;fi
  k="$n/$label"; s=1; [[ "$phase" == Running ]]&&s=2; [[ "$phase" == Running && "$ready" == true ]]&&s=3
  if [[ -z "${GP[$k]:-}" || "$s" -gt "${GS[$k]}" ]];then GN["$k"]="$n";GL["$k"]="$label";GP["$k"]="$pod";GH["$k"]="$phase";GC["$k"]="$containers";GS["$k"]="$s";fi
done < <(jq -r '.items[]|(.metadata.ownerReferences//[]|map(select(.controller==true))|.[0]) as $o|([.spec.containers[]?.name]+[.spec.initContainers[]?.name]|join(",")) as $c|([.status.containerStatuses[]?.ready]|if length==0 then false else all end) as $r|[.metadata.namespace,.metadata.name,.status.phase//"Unknown",($r|tostring),$o.kind//"-",$o.name//"-",$c]|@tsv' <<< "$PODS")

check(){ local f="$1" n="$2" d="$3" p="$4" c="$5" ph="$6" o rc tm tz z; o="$(kx exec -n "$n" "$p" -c "$c" -- sh -c 'tm=$(date "+%Y-%m-%d %H:%M:%S %Z %z" 2>/dev/null||true);tz=$(date "+%Z" 2>/dev/null||true);z=$(cat /etc/timezone 2>/dev/null||true);l=$(readlink /etc/localtime 2>/dev/null||true);printf "%s\n%s\n%s\n" "$tm" "$tz" "$z${z:+;}$l"' 2>&1)";rc=$?;if ((rc==0));then tm="$(sed -n 1p<<<"$o"|tr '\t\r\n' '   ')";tz="$(sed -n 2p<<<"$o"|tr '\t\r\n' '   ')";z="$(sed -n 3p<<<"$o"|tr '\t\r\n' '   ')";r=OK;else tm=-;tz=-;z="$(tr '\t\r\n' '   '<<<"$o"|cut -c1-300)";r="EXEC_FAILED(rc=$rc)";fi;printf '%s\t%s\t%s\t%s\tcontainer\t%s\t%s\t%s\t%s\t%s\n' "$n" "$d" "$p" "$c" "$ph" "$r" "$tm" "$tz" "$z">"$f"; }
mkdir -p "$TMP/r"; files=(); pids=(); id=0
if ((${#GP[@]} > 0)); then
  for k in "${!GP[@]}"; do n="${GN[$k]}";d="${GL[$k]}";p="${GP[$k]}";ph="${GH[$k]}";IFS=',' read -ra cs<<<"${GC[$k]}";for c in "${cs[@]}";do [[ -n "$c" ]]||continue;id=$((id+1));f="$TMP/r/$id";files+=("$f");check "$f" "$n" "$d" "$p" "$c" "$ph"&pids+=("$!");if (( ${#pids[@]}>=PARALLEL ));then for q in "${pids[@]}";do wait "$q" 2>/dev/null||true;done;pids=();fi;done
  done
fi
if ((${#pids[@]} > 0)); then
  for q in "${pids[@]}";do wait "$q" 2>/dev/null||true;done
fi
DATA="$TMP/data"; ((${#files[@]}))&&cat "${files[@]}">"$DATA"||:>"$DATA";total="$(wc -l<"$DATA")";ok="$(awk -F '\t' '$7=="OK"{n++}END{print n+0}' "$DATA")";bad=$((total-ok))
{
echo "Kubernetes 容器时间/时区检查报告";echo "生成时间：$(date '+%Y-%m-%d %H:%M:%S %Z %z')";[[ -n "$NS" ]]&&echo "namespace：$NS";echo "代表性 Pod：${#GP[@]}；容器：$total；成功：$ok；失败：$bad；并发：$PARALLEL";echo
echo "===== Deployment 汇总 =====";printf '%-24s %-40s %8s %8s %8s\n' NAMESPACE DEPLOYMENT/WORKLOAD CONTAINER SUCCESS FAILED
awk -F '\t' '{k=$1 SUBSEP $2;t[k]++;if($7=="OK")o[k]++;else f[k]++}END{for(k in t){split(k,a,SUBSEP);printf "%-24s %-40s %8d %8d %8d\n",a[1],a[2],t[k],o[k]+0,f[k]+0}}' "$DATA"|sort;echo
echo "===== 容器明细 =====";printf '%-24s %-32s %-42s %-25s %-14s %-10s %-20s %-28s %-12s %s\n' NAMESPACE DEPLOYMENT/WORKLOAD REPRESENTATIVE_POD CONTAINER TYPE PHASE RESULT TIME TIMEZONE TIMEZONE_FILES
while IFS=$'\t' read -r n d p c ty ph r tm tz z;do printf '%-24s %-32s %-42s %-25s %-14s %-10s %-20s %-28s %-12s %s\n' "$n" "$d" "$p" "$c" "$ty" "$ph" "$r" "$tm" "$tz" "$z";done< <(sort -t $'\t' -k1,1 -k2,2 -k3,3 -k4,4 "$DATA")
}>"$OUT"
echo "检查完成：$OUT；代表性 Pod：${#GP[@]}；容器：$total；成功：$ok；失败：$bad"
