#!/usr/bin/env bash # setup_default_data.sh — 幂等默认数据初始化 # # 用途:确保 CRM-only 部署的默认数据存在且可重复执行。 # # 设计原则: # - 幂等:多次运行产生相同最终状态 # - dry-run 优先:默认只输出将要执行的操作 # - 不修改宿主后端源码 # - 不直写宿主 PG(CRM-only 部署模式无 PG 依赖) set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TS="$(date +%Y%m%d_%H%M%S)" ARTIFACT_DIR="${ARTIFACT_DIR:-$ROOT_DIR/artifacts/default-data/${TS}}" CRM_BASE="${CRM_BASE:-http://127.0.0.1:18190}" CRM_ADMIN_TOKEN=${CRM_ADMIN_TOKEN:-} CRM_ADMIN_USERNAME=${CRM_ADMIN_USERNAME:-admin} CRM_ADMIN_PASSWORD=${CRM_ADMIN_PASSWORD:-} # --- helpers --- die() { echo "FATAL: $*" >&2; exit 1; } info() { echo "INFO: $*"; } warn() { echo "WARN: $*"; } ok() { echo "OK: $*"; } ensure_artifact_dir() { mkdir -p "${ARTIFACT_DIR}" } _curl() { if [[ -n "${CRM_ADMIN_TOKEN}" ]]; then curl -sS --noproxy '*' -H "Authorization: Bearer ${CRM_ADMIN_TOKEN}" "$@" else curl -sS --noproxy '*' "$@" fi } cmd_help() { cat </run-log.json HELP exit 0 } cmd_dry_run() { info "dry-run" mkdir -p "${ARTIFACT_DIR}" info "CRM: ${CRM_BASE}" local h; h="$(_curl "${CRM_BASE}/healthz")" || true [[ "${h}" == "ok" ]] && ok "health: ok" || warn "health: ${h}" local s; s="$(_curl "${CRM_BASE}/api/admin/schema-version" 2>/dev/null)" || s="N/A" info "schema: ${s}" info "dry-run done -> ${ARTIFACT_DIR}/dry-run-summary.json" python3 -c " import json, sys, datetime d = {'ts':datetime.datetime.now().isoformat(),'mode':'dry_run','crm':sys.argv[1],'health':sys.argv[2],'schema':sys.argv[3]} f=open(sys.argv[4],'w'); json.dump(d,f,ensure_ascii=False,indent=2); f.close() " "${CRM_BASE}" "${h}" "${s}" "${ARTIFACT_DIR}/dry-run-summary.json" } cmd_apply() { info "apply" mkdir -p "${ARTIFACT_DIR}" local actions=() local h; h="$(_curl "${CRM_BASE}/healthz")" || true [[ "${h}" != "ok" ]] && die "CRM dead: ${h}" ok "health ok"; actions+=("h:ok") actions+=("schema:$(_curl ${CRM_BASE}/api/admin/schema-version 2>/dev/null || echo N/A)") local a; a="$(_curl "${CRM_BASE}/api/provider-accounts?limit=100" 2>/dev/null)" || a='{}' local n; n=$(echo "${a}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('accounts',d.get('data',[]))))" 2>/dev/null || echo 0) ok "accounts: ${n}"; actions+=("acct:${n}") python3 -c " import json, sys, datetime acts = sys.argv[4].split(';') if sys.argv[4] else [] d = {'ts':datetime.datetime.now().isoformat(),'mode':'applied','crm':sys.argv[1],'schema':sys.argv[2],'accts':int(sys.argv[3]),'actions':acts} f=open(sys.argv[5],'w'); json.dump(d,f,ensure_ascii=False,indent=2); f.close() " "${CRM_BASE}" "${s:-N/A}" "${n:-0}" "$(IFS=';'; echo "${actions[*]}")" "${ARTIFACT_DIR}/apply-summary.json" ok "applied -> ${ARTIFACT_DIR}/apply-summary.json" } case "${1:-}" in --help|-h) cmd_help ;; --dry-run) cmd_dry_run ;; --apply) cmd_apply ;; *) cmd_help ;; esac