#!/bin/bash # generate-bootstrap-config.sh # 从 kubeconfig 生成 bootstrap 配置文件 set -e echo "🔧 OCDP Bootstrap Configuration Generator" echo "========================================" echo "" # 检查依赖 command -v kubectl >/dev/null 2>&1 || { echo "❌ kubectl is required but not installed. Aborting." >&2; exit 1; } command -v jq >/dev/null 2>&1 || { echo "❌ jq is required but not installed. Aborting." >&2; exit 1; } # 默认输出文件 OUTPUT_FILE="${1:-config/bootstrap.json}" # 临时文件 TMP_FILE=$(mktemp) # 创建基础配置结构 cat > "$TMP_FILE" <<'EOF' { "enabled": true, "users": [], "registries": [], "clusters": [] } EOF echo "📋 请按提示输入信息..." echo "" # ===== Admin 用户配置 ===== echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "👤 Admin 用户配置" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" read -p "是否添加初始管理员用户? (y/n) [y]: " ADD_ADMIN ADD_ADMIN=${ADD_ADMIN:-y} if [[ "$ADD_ADMIN" == "y" ]]; then read -p "Admin 用户名: " ADMIN_USER read -sp "Admin 密码: " ADMIN_PASS echo "" read -p "Admin 邮箱 [${ADMIN_USER}@example.local]: " ADMIN_EMAIL ADMIN_EMAIL=${ADMIN_EMAIL:-"${ADMIN_USER}@example.local"} if [[ -z "$ADMIN_USER" || -z "$ADMIN_PASS" ]]; then echo "❌ Admin 用户名和密码不能为空" exit 1 fi TMP_USER=$(jq -n \ --arg username "$ADMIN_USER" \ --arg password "$ADMIN_PASS" \ --arg email "$ADMIN_EMAIL" \ '{username: $username, password: $password, email: $email}') jq ".users += [$TMP_USER]" "$TMP_FILE" > "${TMP_FILE}.tmp" && mv "${TMP_FILE}.tmp" "$TMP_FILE" echo "✅ Admin 用户 '$ADMIN_USER' 已添加" fi echo "" # ===== Registries 配置 ===== echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "📦 Registry 配置" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" read -p "是否添加 Registry? (y/n) [y]: " ADD_REGISTRY ADD_REGISTRY=${ADD_REGISTRY:-y} if [[ "$ADD_REGISTRY" == "y" ]]; then read -p "Registry 名称 [harbor]: " REGISTRY_NAME REGISTRY_NAME=${REGISTRY_NAME:-harbor} read -p "Registry URL: " REGISTRY_URL read -p "Registry 描述 [Harbor Registry]: " REGISTRY_DESC REGISTRY_DESC=${REGISTRY_DESC:-"Harbor Registry"} read -p "Registry 用户名(推荐 Harbor robot 账号): " REGISTRY_USER read -sp "Registry 密码: " REGISTRY_PASS echo "" if [[ -z "$REGISTRY_URL" ]]; then echo "❌ Registry URL 不能为空" exit 1 fi read -p "是否跳过 SSL 验证? (y/n) [n]: " REGISTRY_INSECURE REGISTRY_INSECURE=${REGISTRY_INSECURE:-n} if [[ "$REGISTRY_INSECURE" == "y" ]]; then INSECURE_VALUE="true" else INSECURE_VALUE="false" fi # 添加 Registry 到配置 TMP_REGISTRY=$(jq -n \ --arg name "$REGISTRY_NAME" \ --arg url "$REGISTRY_URL" \ --arg description "$REGISTRY_DESC" \ --arg username "$REGISTRY_USER" \ --arg password "$REGISTRY_PASS" \ --argjson insecure "$INSECURE_VALUE" \ '{name: $name, url: $url, description: $description, username: $username, password: $password, insecure: $insecure}') jq ".registries += [$TMP_REGISTRY]" "$TMP_FILE" > "${TMP_FILE}.tmp" && mv "${TMP_FILE}.tmp" "$TMP_FILE" echo "✅ Registry '$REGISTRY_NAME' 已添加" fi echo "" # ===== Clusters 配置 ===== echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "☸️ Kubernetes Cluster 配置" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" read -p "是否从 kubeconfig 导入 Cluster? (y/n) [y]: " ADD_CLUSTER ADD_CLUSTER=${ADD_CLUSTER:-y} CLUSTER_INDEX=0 while [[ "$ADD_CLUSTER" == "y" ]]; do echo "" echo "--- Cluster $(($CLUSTER_INDEX + 1)) ---" read -p "Cluster 名称 [cluster$(($CLUSTER_INDEX + 1))]: " CLUSTER_NAME CLUSTER_NAME=${CLUSTER_NAME:-cluster$(($CLUSTER_INDEX + 1))} read -p "Cluster 描述: " CLUSTER_DESC echo "" echo "📂 请选择数据源:" echo " 1) 从 kubeconfig 文件提取" echo " 2) 手动输入" read -p "选择 [1]: " DATA_SOURCE DATA_SOURCE=${DATA_SOURCE:-1} if [[ "$DATA_SOURCE" == "1" ]]; then # 从 kubeconfig 提取 read -p "kubeconfig 文件路径 [~/.kube/config]: " KUBECONFIG_PATH KUBECONFIG_PATH=${KUBECONFIG_PATH:-~/.kube/config} KUBECONFIG_PATH="${KUBECONFIG_PATH/#\~/$HOME}" if [[ ! -f "$KUBECONFIG_PATH" ]]; then echo "❌ kubeconfig 文件不存在: $KUBECONFIG_PATH" continue fi # 列出可用的 contexts echo "" echo "📋 可用的 contexts:" kubectl --kubeconfig="$KUBECONFIG_PATH" config get-contexts echo "" read -p "选择 context (留空使用当前 context): " CONTEXT_NAME if [[ -n "$CONTEXT_NAME" ]]; then KUBECTL_OPTS="--kubeconfig=$KUBECONFIG_PATH --context=$CONTEXT_NAME" else KUBECTL_OPTS="--kubeconfig=$KUBECONFIG_PATH" fi # 提取数据 echo "🔍 正在提取 Cluster 配置..." CLUSTER_HOST=$(kubectl $KUBECTL_OPTS config view --raw -o jsonpath='{.clusters[0].cluster.server}') CLUSTER_CA=$(kubectl $KUBECTL_OPTS config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}') CLUSTER_CERT=$(kubectl $KUBECTL_OPTS config view --raw -o jsonpath='{.users[0].user.client-certificate-data}') CLUSTER_KEY=$(kubectl $KUBECTL_OPTS config view --raw -o jsonpath='{.users[0].user.client-key-data}') echo " ✓ Server: $CLUSTER_HOST" echo " ✓ CA Data: ${CLUSTER_CA:0:50}..." echo " ✓ Cert Data: ${CLUSTER_CERT:0:50}..." echo " ✓ Key Data: ${CLUSTER_KEY:0:50}..." else # 手动输入 read -p "API Server 地址: " CLUSTER_HOST echo "请输入 CA 证书数据 (Base64 编码,多行输入以空行结束):" CLUSTER_CA="" while IFS= read -r line; do [[ -z "$line" ]] && break CLUSTER_CA="${CLUSTER_CA}${line}" done echo "请输入客户端证书数据 (Base64 编码,多行输入以空行结束):" CLUSTER_CERT="" while IFS= read -r line; do [[ -z "$line" ]] && break CLUSTER_CERT="${CLUSTER_CERT}${line}" done echo "请输入客户端密钥数据 (Base64 编码,多行输入以空行结束):" CLUSTER_KEY="" while IFS= read -r line; do [[ -z "$line" ]] && break CLUSTER_KEY="${CLUSTER_KEY}${line}" done fi # 添加 Cluster 到配置 TMP_CLUSTER=$(cat < "${TMP_FILE}.tmp" && mv "${TMP_FILE}.tmp" "$TMP_FILE" echo "✅ Cluster '$CLUSTER_NAME' 已添加" CLUSTER_INDEX=$(($CLUSTER_INDEX + 1)) read -p "是否继续添加 Cluster? (y/n) [n]: " ADD_CLUSTER ADD_CLUSTER=${ADD_CLUSTER:-n} done echo "" # ===== 保存配置 ===== echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "💾 保存配置" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" # 格式化 JSON jq '.' "$TMP_FILE" > "$OUTPUT_FILE" rm "$TMP_FILE" echo "✅ Bootstrap 配置已保存到: $OUTPUT_FILE" echo "" # 显示配置摘要 echo "📊 配置摘要:" echo " - 用户数: $(jq '.users | length' "$OUTPUT_FILE")" echo " - Registry 数: $(jq '.registries | length' "$OUTPUT_FILE")" echo " - Cluster 数: $(jq '.clusters | length' "$OUTPUT_FILE")" echo "" echo "🚀 接下来的步骤:" echo " 1. 检查配置文件: cat $OUTPUT_FILE" echo " 2. 启动应用: make run-mock" echo " 3. 验证数据:" echo " curl http://localhost:8080/api/v1/registries" echo " curl http://localhost:8080/api/v1/clusters" echo "" echo "✨ 完成!"