326 lines
9.3 KiB
Bash
326 lines
9.3 KiB
Bash
#!/usr/bin/env bash
|
||
#
|
||
# 逻辑:
|
||
# 1. 检查依赖
|
||
# 2. 若未指定 --name,则用 "本机IPv4(YYYY-MM-DD-HH-mm)"
|
||
# 3. 获取 Token
|
||
# 4. 创建节点 (nodeLogin.params 做 Base64,并包含grantId)
|
||
# 5. 批量添加 IP
|
||
# 6. 获取节点信息
|
||
# 7. 安装节点
|
||
#
|
||
# 依赖:curl, jq, base64
|
||
#
|
||
# 若不加 --grantid,则默认值为 1;
|
||
# 若不加 --name,则自动设置成 "<本机IPv4>(YYYY-MM-DD-HH-mm)"。
|
||
|
||
set -e
|
||
|
||
###############################################################################
|
||
# 函数:检查并安装依赖
|
||
###############################################################################
|
||
function install_deps_if_needed() {
|
||
local packages=("curl" "jq" "base64")
|
||
|
||
# 判断命令是否存在,若不存在,则需要安装
|
||
for pkg in "${packages[@]}"; do
|
||
if ! command -v "$pkg" &> /dev/null; then
|
||
echo "[INFO] 检测到命令 '$pkg' 不存在,需要安装..."
|
||
|
||
# 尝试判断系统使用 apt-get 或 yum 安装
|
||
if command -v apt-get &> /dev/null; then
|
||
echo "[INFO] 检测到系统支持 apt-get,开始安装: $pkg"
|
||
sudo apt-get update -y
|
||
# base64 通常在 coreutils 中,jq 单独包
|
||
sudo apt-get install -y curl jq coreutils
|
||
elif command -v yum &> /dev/null; then
|
||
echo "[INFO] 检测到系统支持 yum,开始安装: $pkg"
|
||
sudo yum install -y curl jq coreutils
|
||
elif command -v dnf &> /dev/null; then
|
||
echo "[INFO] 检测到系统支持 dnf,开始安装: $pkg"
|
||
sudo dnf install -y curl jq coreutils
|
||
elif command -v zypper &> /dev/null; then
|
||
echo "[INFO] 检测到系统支持 zypper,开始安装: $pkg"
|
||
sudo zypper install -y curl jq coreutils
|
||
else
|
||
echo "[ERROR] 不支持的包管理器,无法自动安装 $pkg,请手动安装。"
|
||
exit 1
|
||
fi
|
||
|
||
# 再次检测命令是否成功安装
|
||
if ! command -v "$pkg" &> /dev/null; then
|
||
echo "[ERROR] 安装 $pkg 失败,请手动安装后再试。"
|
||
exit 1
|
||
fi
|
||
fi
|
||
done
|
||
}
|
||
|
||
###############################################################################
|
||
# 开始脚本逻辑
|
||
###############################################################################
|
||
# 1. 检查依赖
|
||
install_deps_if_needed
|
||
|
||
###############################################################################
|
||
# 解析命令行参数
|
||
###############################################################################
|
||
ACID=""
|
||
ACKEY=""
|
||
NAME=""
|
||
CLUSTER_ID=""
|
||
GROUP_ID=0
|
||
REGION_ID=0
|
||
DNS_ROUTES=""
|
||
API_HOST=""
|
||
GRANT_ID=1 # 默认值
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--acid)
|
||
ACID="$2"
|
||
shift 2
|
||
;;
|
||
--ackey)
|
||
ACKEY="$2"
|
||
shift 2
|
||
;;
|
||
--name)
|
||
NAME="$2"
|
||
shift 2
|
||
;;
|
||
--clusterid)
|
||
CLUSTER_ID="$2"
|
||
shift 2
|
||
;;
|
||
--grantid)
|
||
GRANT_ID="$2"
|
||
shift 2
|
||
;;
|
||
--groupid)
|
||
GROUP_ID="$2"
|
||
shift 2
|
||
;;
|
||
--regionid)
|
||
REGION_ID="$2"
|
||
shift 2
|
||
;;
|
||
--dnsroutes)
|
||
DNS_ROUTES="$2"
|
||
shift 2
|
||
;;
|
||
--api-host)
|
||
API_HOST="$2"
|
||
shift 2
|
||
;;
|
||
*)
|
||
echo "[ERROR] 未知参数: $1"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# 基础校验
|
||
if [[ -z "$ACID" || -z "$ACKEY" || -z "$CLUSTER_ID" ]]; then
|
||
echo "[ERROR] 用法: $0 --acid <ACCESS_KEY_ID> --ackey <ACCESS_KEY> --clusterid <CLUSTER_ID> [--grantid <GRANT_ID>] [--name <NAME>] [--groupid <GROUP_ID>] [--regionid <REGION_ID>] [--dnsroutes <DNS_ROUTES>] [--api-host <API_HOST>]"
|
||
exit 1
|
||
fi
|
||
|
||
###############################################################################
|
||
# 先获取本机 IPv4,用于创建节点时的 nodeLogin 和 “自动名称”逻辑
|
||
###############################################################################
|
||
echo "[INFO] 获取本机 IPv4 地址..."
|
||
LOCAL_IPV4=$(curl -s 4.ipw.cn || true)
|
||
if [[ -z "$LOCAL_IPV4" ]]; then
|
||
echo "[WARN] 获取IPv4失败,使用0.0.0.0"
|
||
LOCAL_IPV4="0.0.0.0"
|
||
fi
|
||
echo "[INFO] 本机 IPv4: $LOCAL_IPV4"
|
||
|
||
# 如果没指定 --name,就自动生成一个 "<本机IPv4>(YYYY-MM-DD-HH-mm)" 格式名称
|
||
if [[ -z "$NAME" ]]; then
|
||
DATE_STR=$(date +%Y-%m-%d-%H-%M)
|
||
NAME="${LOCAL_IPV4}(${DATE_STR})"
|
||
echo "[INFO] 未指定 --name,自动设置 NAME=$NAME"
|
||
fi
|
||
|
||
|
||
###############################################################################
|
||
# 2. 获取 Token
|
||
###############################################################################
|
||
echo "[INFO] 正在获取 Token..."
|
||
|
||
get_token_resp=$(curl -s -X POST \
|
||
-H "Content-Type: application/json" \
|
||
"$API_HOST/APIAccessTokenService/getAPIAccessToken" \
|
||
-d '{
|
||
"type": "admin",
|
||
"accessKeyId": "'"$ACID"'",
|
||
"accessKey": "'"$ACKEY"'"
|
||
}')
|
||
get_token_code=$(echo "$get_token_resp" | jq -r '.code')
|
||
if [ "$get_token_code" != "200" ]; then
|
||
echo "[ERROR] 获取Token失败,响应: $get_token_resp"
|
||
exit 1
|
||
fi
|
||
TOKEN=$(echo "$get_token_resp" | jq -r '.data.token')
|
||
echo "[INFO] 成功获取 Token"
|
||
|
||
###############################################################################
|
||
# 3. 创建节点 (NodeService/createNode)
|
||
# nodeLogin.params 是 bytes 类型,所以先把 JSON Base64 编码
|
||
###############################################################################
|
||
echo "[INFO] 正在创建节点..."
|
||
|
||
# 处理 DNS_ROUTES => JSON 数组
|
||
if [[ -n "$DNS_ROUTES" ]]; then
|
||
dns_routes_json_array=$(echo "$DNS_ROUTES" | sed 's/ /","/g')
|
||
dns_routes_json_array="[\"$dns_routes_json_array\"]"
|
||
else
|
||
dns_routes_json_array="[]"
|
||
fi
|
||
|
||
# nodeLogin.params 的原始 JSON
|
||
# 加入 grantId=$GRANT_ID
|
||
node_login_json=$(cat <<EOF
|
||
{
|
||
"host": "$LOCAL_IPV4",
|
||
"port": 22,
|
||
"grantId": $GRANT_ID
|
||
}
|
||
EOF
|
||
)
|
||
|
||
# 用 base64 编码
|
||
BASE64_PARAMS=$(echo -n "$node_login_json" | base64 | tr -d '\n')
|
||
|
||
create_node_payload=$(cat <<EOF
|
||
{
|
||
"name": "$NAME",
|
||
"nodeClusterId": $CLUSTER_ID,
|
||
"nodeLogin": {
|
||
"id": 3,
|
||
"name": "SSH",
|
||
"type": "ssh",
|
||
"params": "$BASE64_PARAMS"
|
||
},
|
||
"nodeGroupId": $GROUP_ID,
|
||
"dnsRoutes": $dns_routes_json_array,
|
||
"nodeRegionId": $REGION_ID
|
||
}
|
||
EOF
|
||
)
|
||
|
||
echo "[INFO] createNode 请求体:$create_node_payload"
|
||
create_node_resp=$(curl -s -X POST \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-Edge-Access-Token: $TOKEN" \
|
||
"$API_HOST/NodeService/createNode" \
|
||
-d "$create_node_payload"
|
||
)
|
||
create_node_code=$(echo "$create_node_resp" | jq -r '.code')
|
||
if [ "$create_node_code" != "200" ]; then
|
||
echo "[ERROR] 创建节点失败,响应: $create_node_resp"
|
||
exit 1
|
||
fi
|
||
|
||
NODE_ID=$(echo "$create_node_resp" | jq -r '.data.nodeId')
|
||
echo "[INFO] 节点创建成功,nodeId = $NODE_ID"
|
||
|
||
###############################################################################
|
||
# 4. 批量创建 IP (NodeIPAddressService/createNodeIPAddresses)
|
||
###############################################################################
|
||
echo "[INFO] 正在获取本机 IPv6 地址..."
|
||
LOCAL_IPV6=$(curl -s 6.ipw.cn || true)
|
||
if [[ -z "$LOCAL_IPV6" ]]; then
|
||
echo "[WARN] 本机 IPv6 获取失败或不存在"
|
||
fi
|
||
echo "[INFO] 本机 IPv6: $LOCAL_IPV6"
|
||
|
||
echo "[INFO] 批量创建 IP 地址 (createNodeIPAddresses) ..."
|
||
ip_array='["'"$LOCAL_IPV4"'"]'
|
||
if [[ -n "$LOCAL_IPV6" ]]; then
|
||
ip_array='["'"$LOCAL_IPV4"'","'"$LOCAL_IPV6"'"]'
|
||
fi
|
||
|
||
create_ips_payload=$(cat <<EOF
|
||
{
|
||
"nodeId": $NODE_ID,
|
||
"role": "node",
|
||
"name": "auto-ips",
|
||
"ipList": $ip_array,
|
||
"canAccess": true,
|
||
"isUp": true,
|
||
"groupValue": "",
|
||
"nodeClusterIds": []
|
||
}
|
||
EOF
|
||
)
|
||
|
||
echo "[INFO] createNodeIPAddresses 请求体:$create_ips_payload"
|
||
create_ips_resp=$(curl -s -X POST \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-Edge-Access-Token: $TOKEN" \
|
||
"$API_HOST/NodeIPAddressService/createNodeIPAddresses" \
|
||
-d "$create_ips_payload"
|
||
)
|
||
create_ips_code=$(echo "$create_ips_resp" | jq -r '.code')
|
||
if [ "$create_ips_code" != "200" ]; then
|
||
echo "[ERROR] 创建 IP 地址失败,响应: $create_ips_resp"
|
||
exit 1
|
||
fi
|
||
|
||
ADDR_IDS=$(echo "$create_ips_resp" | jq -r '.data.nodeIPAddressIds')
|
||
echo "[INFO] 已为节点 $NODE_ID 批量创建 IP 地址, nodeIPAddressIds = $ADDR_IDS"
|
||
echo
|
||
|
||
###############################################################################
|
||
# 5. 获取节点信息 (findEnabledNode)
|
||
###############################################################################
|
||
echo "[INFO] 查找节点信息 (findEnabledNode)..."
|
||
find_node_resp=$(curl -s -X POST \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-Edge-Access-Token: $TOKEN" \
|
||
"$API_HOST/NodeService/findEnabledNode" \
|
||
-d '{
|
||
"nodeId": '"$NODE_ID"'
|
||
}'
|
||
)
|
||
|
||
find_node_code=$(echo "$find_node_resp" | jq -r '.code')
|
||
if [ "$find_node_code" != "200" ]; then
|
||
echo "[ERROR] 获取节点信息失败, 响应: $find_node_resp"
|
||
exit 1
|
||
fi
|
||
|
||
node_info=$(echo "$find_node_resp" | jq -r '.data.node')
|
||
|
||
###############################################################################
|
||
# 6. 安装节点 (NodeService/installNode)
|
||
###############################################################################
|
||
echo "[INFO] 正在安装节点..."
|
||
install_node_payload=$(cat <<EOF
|
||
{
|
||
"nodeId": $NODE_ID
|
||
}
|
||
EOF
|
||
)
|
||
|
||
install_node_resp=$(curl -s -X POST \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-Edge-Access-Token: $TOKEN" \
|
||
"$API_HOST/NodeService/installNode" \
|
||
-d "$install_node_payload"
|
||
)
|
||
install_node_code=$(echo "$install_node_resp" | jq -r '.code')
|
||
if [ "$install_node_code" != "200" ]; then
|
||
echo "[ERROR] 安装节点失败, 响应: $install_node_resp"
|
||
exit 1
|
||
fi
|
||
|
||
echo "[INFO] 已请求节点安装,请等待节点安装完成后上线。"
|
||
echo
|
||
|
||
echo "[INFO] 脚本执行完成。"
|
||
exit 0
|