#!/usr/bin/env bash # 从 Consul 导出 KV 到 idwms/*.json(首次建仓 / 对账用) # 注意:导出会含明文密码,勿直接 commit;先人工脱敏或改用占位符 # 用法: ./scripts/export-from-consul.sh [admin|common|itfxapi|trackapi ...] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" export KUBECONFIG="${KUBECONFIG:-/etc/rancher/k3s/k3s.yaml}" NS="${NAMESPACE:-prod}" IDWMS_DIR="${ROOT}/idwms" mkdir -p "$IDWMS_DIR" need() { command -v "$1" >/dev/null || { echo "FAIL: 需要 $1"; exit 1; }; } need kubectl need curl command -v python3 >/dev/null || command -v jq >/dev/null || { echo "FAIL: 需要 python3 或 jq"; exit 1; } json_pretty() { local raw="$1" out="$2" if command -v python3 >/dev/null; then python3 -c 'import json,sys; json.dump(json.load(sys.stdin), open(sys.argv[1],"w",encoding="utf-8"), ensure_ascii=False, indent=2); open(sys.argv[1],"a",encoding="utf-8").write("\n")' "$out" <<<"$raw" else jq . <<<"$raw" >"$out" fi } json_ok_str() { local raw="$1" if command -v python3 >/dev/null; then python3 -c 'import json,sys; json.loads(sys.stdin.read())' <<<"$raw" else jq empty <<<"$raw" fi } # Consul:跨集群时 ClusterIP 不可达 → port-forward CONSUL_PF_PID="" cleanup_pf() { if [[ -n "${CONSUL_PF_PID:-}" ]]; then kill "$CONSUL_PF_PID" 2>/dev/null || true wait "$CONSUL_PF_PID" 2>/dev/null || true CONSUL_PF_PID="" fi } trap cleanup_pf EXIT if [[ -z "${CONSUL_HTTP_ADDR:-}" ]]; then LOCAL_PORT=18510 echo "==> port-forward svc/consul → 127.0.0.1:${LOCAL_PORT} (ns=${NS})" kubectl -n "$NS" port-forward svc/consul "${LOCAL_PORT}:8500" >/tmp/consul-pf-export-${NS}.log 2>&1 & CONSUL_PF_PID=$! ok=0 for _ in $(seq 1 40); do if curl -sf --connect-timeout 1 "http://127.0.0.1:${LOCAL_PORT}/v1/status/leader" >/dev/null 2>&1; then ok=1 break fi sleep 0.5 done [[ "$ok" == "1" ]] || { echo "FAIL: Consul port-forward 未就绪"; cat /tmp/consul-pf-export-${NS}.log 2>/dev/null || true; exit 1; } CONSUL_HTTP_ADDR="http://127.0.0.1:${LOCAL_PORT}" fi echo "==> Consul ${CONSUL_HTTP_ADDR}" if [[ -z "${CONSUL_HTTP_TOKEN:-}" ]]; then raw="$(kubectl -n "$NS" get secret consul-acl -o jsonpath='{.data.CONSUL_HTTP_TOKEN}' 2>/dev/null || true)" if [[ -n "$raw" ]]; then CONSUL_HTTP_TOKEN="$(printf '%s' "$raw" | base64 -d)" fi fi CURL_AUTH=() if [[ -n "${CONSUL_HTTP_TOKEN:-}" ]]; then CURL_AUTH=(-H "X-Consul-Token: ${CONSUL_HTTP_TOKEN}") fi if [[ $# -eq 0 ]]; then TARGETS=(common admin itfxapi trackapi) else TARGETS=("$@") fi for name in "${TARGETS[@]}"; do key="idwms/${name}" out="${IDWMS_DIR}/${name}.json" echo "==> GET ${key}" raw="$(curl -sS "${CURL_AUTH[@]}" "${CONSUL_HTTP_ADDR}/v1/kv/${key}?raw" || true)" if [[ -z "$raw" ]]; then echo "WARN: ${key} 为空或不存在,跳过" continue fi if ! json_ok_str "$raw" 2>/dev/null; then echo "FAIL: ${key} 不是 JSON" exit 1 fi json_pretty "$raw" "$out" echo "OK → ${out}" done echo "导出完成。提交前请把密码改成 \${MYSQL_ROOT_PASSWORD} 等占位符。"