- 工具配置:新增卸载 API/UI、Go 工具链、流水线构建自动安装依赖 - 修复 ListTools VerifyTool 递归栈溢出导致获取工具配置失败 - Node.js Alpine 安装改用 unofficial-builds musl 预编译包与 index.json 解析 LTS - 站点拨测:详情页路由、告警自动恢复、并发拨测与默认可观测频率 - 日志中心:RBAC、查询构建器、ES/Loki 增强与审计 request/response 展示 - 发布配置:构建节点、流水线远程执行、Deploy RBAC 导航拆分
383 lines
16 KiB
Go
383 lines
16 KiB
Go
package model
|
||
|
||
import "time"
|
||
|
||
// ============================================
|
||
// DeployTool 工具配置(懒加载/预装/禁用)
|
||
// 按 deploy_ 前缀,与 PipelineRepo/Registry 同属发布配置域
|
||
// ============================================
|
||
|
||
// ToolInstallMethod 安装方式
|
||
type ToolInstallMethod string
|
||
|
||
const (
|
||
ToolPreinstall ToolInstallMethod = "preinstall" // 预装在 Dockerfile 中
|
||
ToolLazy ToolInstallMethod = "lazy" // 懒加载:首次使用时自动下载
|
||
ToolDisabled ToolInstallMethod = "disabled" // 禁用:不安装
|
||
)
|
||
|
||
// ToolStatus 安装状态
|
||
type ToolStatus string
|
||
|
||
const (
|
||
ToolNotInstalled ToolStatus = "not_installed" // 未安装
|
||
ToolInstalling ToolStatus = "installing" // 安装中
|
||
ToolInstalled ToolStatus = "installed" // 已安装
|
||
ToolFailed ToolStatus = "failed" // 安装失败
|
||
)
|
||
|
||
// DeployTool 工具配置表
|
||
type DeployTool struct {
|
||
ID uint `gorm:"primaryKey;autoIncrement;comment:主键ID" json:"id"`
|
||
Name string `gorm:"type:varchar(64);uniqueIndex;not null;comment:工具名称(英文标识)" json:"name"`
|
||
DisplayName string `gorm:"type:varchar(128);not null;comment:显示名称" json:"display_name"`
|
||
Description string `gorm:"type:varchar(256);comment:工具描述" json:"description,omitempty"`
|
||
Category string `gorm:"type:varchar(32);default:other;comment:分类: k8s/build/deploy/automation" json:"category"`
|
||
InstallMethod ToolInstallMethod `gorm:"type:varchar(16);default:lazy;comment:安装方式: preinstall/lazy/disabled" json:"install_method"`
|
||
CheckCommand string `gorm:"type:varchar(256);comment:检测命令(如 kubectl version --client)" json:"check_command,omitempty"`
|
||
BinaryName string `gorm:"type:varchar(64);comment:二进制文件名(如 kubectl/mvn/node)" json:"binary_name,omitempty"`
|
||
InstallPath string `gorm:"type:varchar(256);comment:安装目标路径(如 /usr/local/bin)" json:"install_path,omitempty"`
|
||
DownloadURL string `gorm:"type:varchar(512);comment:下载地址模板(支持 {version})" json:"download_url,omitempty"`
|
||
VersionURL string `gorm:"type:varchar(512);comment:版本查询地址(如 stable.txt)" json:"version_url,omitempty"`
|
||
InstallScript string `gorm:"type:text;comment:自定义安装脚本(Shell)" json:"install_script,omitempty"`
|
||
DefaultVersion string `gorm:"type:varchar(32);comment:默认版本号" json:"default_version,omitempty"`
|
||
Status ToolStatus `gorm:"type:varchar(16);default:not_installed;comment:当前安装状态" json:"status"`
|
||
InstalledVer string `gorm:"type:varchar(128);comment:已安装版本号" json:"installed_version,omitempty"`
|
||
LastCheck *time.Time `gorm:"comment:最后检测时间" json:"last_check,omitempty"`
|
||
ErrorMsg string `gorm:"type:varchar(512);comment:安装失败原因" json:"error_msg,omitempty"`
|
||
Enabled bool `gorm:"default:true;comment:是否启用" json:"enabled"`
|
||
SortOrder int `gorm:"default:0;comment:排序" json:"sort_order"`
|
||
CreatedAt time.Time `gorm:"not null;comment:创建时间" json:"created_at"`
|
||
UpdatedAt time.Time `gorm:"not null;comment:更新时间" json:"updated_at"`
|
||
}
|
||
|
||
// TableName 表名
|
||
func (DeployTool) TableName() string {
|
||
return "deploy_tools"
|
||
}
|
||
|
||
// ============================================
|
||
// 预置工具定义(Seeder)— 精简版 v2
|
||
// 移除: kubectl(Dockerfile 预装)、helm(非核心)
|
||
// 新增: nvm(管理 Node 版本)、jdk(Java 构建)
|
||
// ============================================
|
||
|
||
// PredefinedTools 返回系统预置的工具配置列表
|
||
func PredefinedTools() []DeployTool {
|
||
return []DeployTool{
|
||
// ──── JDK — Java 构建 // Logan.Li ────
|
||
{
|
||
Name: "jdk",
|
||
DisplayName: "JDK (Java)",
|
||
Description: "Java 开发工具包,流水线 Java/Maven 构建阶段使用",
|
||
Category: "build",
|
||
InstallMethod: ToolLazy,
|
||
BinaryName: "java",
|
||
InstallPath: "/usr/local/bin/java",
|
||
CheckCommand: "/usr/local/bin/java -version 2>&1 | head -1",
|
||
VersionURL: "https://api.adoptium.net/v3/info/release_versions?heap_size=normal&image_type=jdk&page=0&page_size=1&project=jdk&release_type=ga&semver=false&sort_method=DEFAULT&sort_order=DESC&version=%5B17%2C99%5D",
|
||
DownloadURL: "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-{version}/OpenJDK17U-jdk_x64_linux_hotspot_{version}.tar.gz",
|
||
DefaultVersion: "17.0.13+7",
|
||
InstallScript: `#!/bin/sh
|
||
# JDK lazy install — Alpine apk 优先,否则 Adoptium API 多镜像 // Logan.Li
|
||
JDK_VERSION="${TOOL_VERSION:-17.0.13+7}"
|
||
JDK_MAJOR=$(echo "$JDK_VERSION" | cut -d. -f1)
|
||
JDK_FILE_VER=$(echo "$JDK_VERSION" | tr '+' '_')
|
||
echo "[JDK] Installing ${JDK_VERSION} (major ${JDK_MAJOR})..."
|
||
|
||
if command -v apk >/dev/null 2>&1; then
|
||
case "$JDK_MAJOR" in
|
||
11) APK_PKG="openjdk11-jdk" ;;
|
||
17) APK_PKG="openjdk17-jdk" ;;
|
||
21) APK_PKG="openjdk21-jdk" ;;
|
||
*) APK_PKG="" ;;
|
||
esac
|
||
if [ -n "$APK_PKG" ]; then
|
||
echo "[JDK] Trying apk: $APK_PKG"
|
||
if apk add --no-cache "$APK_PKG"; then
|
||
JAVA_BIN=$(command -v java 2>/dev/null || echo "/usr/lib/jvm/java-${JDK_MAJOR}-openjdk/bin/java")
|
||
mkdir -p /usr/local/bin /usr/local/share/jdk/bin
|
||
ln -sf "$JAVA_BIN" /usr/local/bin/java
|
||
ln -sf "$(dirname "$JAVA_BIN")/javac" /usr/local/bin/javac 2>/dev/null || true
|
||
ln -sf "$(dirname "$JAVA_BIN")/jar" /usr/local/bin/jar 2>/dev/null || true
|
||
echo "[JDK] Installed via apk: $(java -version 2>&1 | head -1)"
|
||
exit 0
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
cd /tmp && rm -rf jdk.tar.gz jdk-install
|
||
mkdir -p jdk-install && cd jdk-install
|
||
DOWNLOADED=0
|
||
for URL in \
|
||
"https://api.adoptium.net/v3/binary/version/${JDK_VERSION}/linux/x64/jdk/hotspot/normal/eclipse?project=jdk" \
|
||
"https://mirrors.tuna.tsinghua.edu.cn/Adoptium/${JDK_MAJOR}/jdk/${JDK_VERSION}/OpenJDK${JDK_MAJOR}U-jdk_x64_linux_hotspot_${JDK_FILE_VER}.tar.gz" \
|
||
"https://github.com/adoptium/temurin${JDK_MAJOR}-binaries/releases/download/jdk-${JDK_VERSION}/OpenJDK${JDK_MAJOR}U-jdk_x64_linux_hotspot_${JDK_FILE_VER}.tar.gz"
|
||
do
|
||
echo "[JDK] Trying $URL"
|
||
if curl -fsSL -L -o jdk.tar.gz "$URL"; then
|
||
DOWNLOADED=1
|
||
break
|
||
fi
|
||
rm -f jdk.tar.gz
|
||
done
|
||
[ "$DOWNLOADED" -eq 1 ] || { echo "[JDK] all mirrors failed"; exit 1; }
|
||
tar xzf jdk.tar.gz
|
||
JDK_DIR=$(find . -maxdepth 1 -type d -name 'jdk-*' | head -1)
|
||
[ -n "$JDK_DIR" ] || { echo "[JDK] extract dir not found"; exit 1; }
|
||
mkdir -p /usr/local/share
|
||
rm -rf /usr/local/share/jdk
|
||
mv "$JDK_DIR" /usr/local/share/jdk
|
||
ln -sf /usr/local/share/jdk/bin/java /usr/local/bin/java
|
||
ln -sf /usr/local/share/jdk/bin/javac /usr/local/bin/javac
|
||
ln -sf /usr/local/share/jdk/bin/jar /usr/local/bin/jar
|
||
cd /tmp && rm -rf jdk-install
|
||
echo "[JDK] Installed: $(/usr/local/bin/java -version 2>&1 | head -1)"
|
||
`,
|
||
SortOrder: 1,
|
||
},
|
||
// ──── Maven — Java 构建 // Logan.Li ────
|
||
{
|
||
Name: "maven",
|
||
DisplayName: "Maven",
|
||
Description: "Java 项目构建工具,流水线 Java 构建阶段使用(依赖 JDK)",
|
||
Category: "build",
|
||
InstallMethod: ToolLazy,
|
||
BinaryName: "mvn",
|
||
InstallPath: "/usr/local/bin/mvn",
|
||
CheckCommand: "/usr/local/bin/mvn --version 2>/dev/null | head -1",
|
||
DownloadURL: "https://dlcdn.apache.org/maven/maven-3/{version}/binaries/apache-maven-{version}-bin.tar.gz",
|
||
VersionURL: "https://dlcdn.apache.org/maven/maven-3/",
|
||
DefaultVersion: "3.9.9",
|
||
InstallScript: `#!/bin/sh
|
||
# Maven lazy install — 多镜像轮询 // Logan.Li
|
||
MAVEN_VERSION="${TOOL_VERSION:-3.9.9}"
|
||
echo "[Maven] Downloading ${MAVEN_VERSION}..."
|
||
cd /tmp && rm -rf maven.tar.gz maven-install
|
||
mkdir -p maven-install && cd maven-install
|
||
DOWNLOADED=0
|
||
for URL in \
|
||
"https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \
|
||
"https://repo.huaweicloud.com/apache/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \
|
||
"https://dlcdn.apache.org/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \
|
||
"https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz"
|
||
do
|
||
echo "[Maven] Trying $URL"
|
||
if curl -fsSL -o maven.tar.gz "$URL"; then
|
||
DOWNLOADED=1
|
||
break
|
||
fi
|
||
rm -f maven.tar.gz
|
||
done
|
||
[ "$DOWNLOADED" -eq 1 ] || { echo "[Maven] all mirrors failed"; exit 1; }
|
||
tar xzf maven.tar.gz
|
||
MVN_DIR=$(find . -maxdepth 1 -type d -name 'apache-maven-*' | head -1)
|
||
[ -n "$MVN_DIR" ] || { echo "[Maven] extract dir not found"; exit 1; }
|
||
mkdir -p /usr/local/share
|
||
rm -rf /usr/local/share/maven
|
||
mv "$MVN_DIR" /usr/local/share/maven
|
||
ln -sf /usr/local/share/maven/bin/mvn /usr/local/bin/mvn
|
||
cd /tmp && rm -rf maven-install
|
||
echo "[Maven] Installed: $(/usr/local/bin/mvn --version 2>&1 | head -1)"
|
||
`,
|
||
SortOrder: 2,
|
||
},
|
||
// ──── Go — 后端构建 // Logan.Li ────
|
||
{
|
||
Name: "golang",
|
||
DisplayName: "Go (Golang)",
|
||
Description: "Go 语言工具链,流水线 go build/test 阶段使用",
|
||
Category: "build",
|
||
InstallMethod: ToolLazy,
|
||
BinaryName: "go",
|
||
InstallPath: "/usr/local/bin/go",
|
||
CheckCommand: "/usr/local/bin/go version 2>/dev/null",
|
||
DownloadURL: "https://go.dev/dl/go{version}.linux-amd64.tar.gz",
|
||
DefaultVersion: "1.24.0",
|
||
InstallScript: `#!/bin/sh
|
||
# Go lazy install — 国内镜像优先 // Logan.Li
|
||
GO_VERSION="${TOOL_VERSION:-1.24.0}"
|
||
GO_VERSION="${GO_VERSION#go}"
|
||
echo "[Go] Installing go${GO_VERSION}..."
|
||
cd /tmp && rm -rf go.tar.gz go-install
|
||
mkdir -p go-install && cd go-install
|
||
DOWNLOADED=0
|
||
for URL in \
|
||
"https://golang.google.cn/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||
"https://mirrors.aliyun.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||
"https://mirrors.ustc.edu.cn/golang/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||
"https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz"
|
||
do
|
||
echo "[Go] Trying $URL"
|
||
if curl -fsSL -L -o go.tar.gz "$URL"; then
|
||
DOWNLOADED=1
|
||
break
|
||
fi
|
||
rm -f go.tar.gz
|
||
done
|
||
[ "$DOWNLOADED" -eq 1 ] || { echo "[Go] all mirrors failed"; exit 1; }
|
||
tar xzf go.tar.gz
|
||
[ -d go ] || { echo "[Go] extract dir not found"; exit 1; }
|
||
rm -rf /usr/local/go
|
||
mv go /usr/local/go
|
||
mkdir -p /usr/local/bin
|
||
ln -sf /usr/local/go/bin/go /usr/local/bin/go
|
||
ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt
|
||
mkdir -p /etc/profile.d
|
||
cat > /etc/profile.d/golang.sh << 'GO_PROFILE'
|
||
export GOROOT=/usr/local/go
|
||
export PATH=$GOROOT/bin:$PATH
|
||
export GOPROXY=https://goproxy.cn,direct
|
||
export GOTOOLCHAIN=local
|
||
GO_PROFILE
|
||
chmod +x /etc/profile.d/golang.sh
|
||
export GOROOT=/usr/local/go
|
||
export PATH=$GOROOT/bin:$PATH
|
||
export GOPROXY=https://goproxy.cn,direct
|
||
export GOTOOLCHAIN=local
|
||
echo "[Go] Installed: $(/usr/local/bin/go version)"
|
||
`,
|
||
SortOrder: 3,
|
||
},
|
||
// ──── NVM — Node Version Manager // Logan.Li ────
|
||
{
|
||
Name: "nvm",
|
||
DisplayName: "NVM (Node 版本管理)",
|
||
Description: "Node 版本管理器,流水线 Node.js 构建阶段使用(node 依赖此工具)",
|
||
Category: "build",
|
||
InstallMethod: ToolLazy,
|
||
BinaryName: "nvm",
|
||
InstallPath: "/usr/local/share/nvm/nvm.sh",
|
||
CheckCommand: ". /usr/local/share/nvm/nvm.sh 2>/dev/null && nvm --version 2>/dev/null",
|
||
VersionURL: "https://api.github.com/repos/nvm-sh/nvm/releases/latest",
|
||
DefaultVersion: "0.40.1",
|
||
InstallScript: `#!/bin/sh
|
||
# NVM lazy install — 使用 bash 执行官方脚本 // Logan.Li
|
||
NVM_VERSION="${TOOL_VERSION:-0.40.1}"
|
||
NVM_DIR="/usr/local/share/nvm"
|
||
echo "[NVM] Downloading v${NVM_VERSION}..."
|
||
mkdir -p "$NVM_DIR"
|
||
curl -fsSL "https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh" -o /tmp/nvm-install.sh
|
||
export NVM_DIR
|
||
bash /tmp/nvm-install.sh
|
||
rm -f /tmp/nvm-install.sh
|
||
[ -s "$NVM_DIR/nvm.sh" ] || { echo "[NVM] nvm.sh not found"; exit 1; }
|
||
mkdir -p /etc/profile.d
|
||
cat > /etc/profile.d/nvm.sh << 'NVM_PROFILE'
|
||
export NVM_DIR="/usr/local/share/nvm"
|
||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
||
NVM_PROFILE
|
||
chmod +x /etc/profile.d/nvm.sh
|
||
. "$NVM_DIR/nvm.sh"
|
||
echo "[NVM] Installed: $(nvm --version 2>/dev/null || echo v${NVM_VERSION})"
|
||
`,
|
||
SortOrder: 4,
|
||
},
|
||
// ──── Node.js — 通过 NVM 安装 // Logan.Li ────
|
||
{
|
||
Name: "nodejs",
|
||
DisplayName: "Node.js + npm",
|
||
Description: "前端构建工具,流水线 npm install/build 阶段使用(通过 NVM 安装)",
|
||
Category: "build",
|
||
InstallMethod: ToolLazy,
|
||
BinaryName: "node",
|
||
InstallPath: "/usr/local/bin/node",
|
||
CheckCommand: "node --version 2>/dev/null",
|
||
DefaultVersion: "lts",
|
||
InstallScript: `#!/bin/sh
|
||
# Node.js 安装 — Alpine 用 unofficial-builds musl 包(官方已停 musl 预编译)// Logan.Li
|
||
NODE_VERSION="${TOOL_VERSION:-lts}"
|
||
NVM_DIR="/usr/local/share/nvm"
|
||
NODE_MIRROR="${NODE_MIRROR:-https://npmmirror.com/mirrors/node}"
|
||
echo "[Node.js] Installing (${NODE_VERSION})..."
|
||
mkdir -p "$NVM_DIR/versions/node"
|
||
export NVM_DIR
|
||
|
||
resolve_version() {
|
||
case "$1" in
|
||
lts)
|
||
curl -fsSL "https://nodejs.org/dist/index.json" 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(next(x['version'] for x in d if x.get('lts')))" 2>/dev/null || echo "v24.18.0"
|
||
;;
|
||
latest|node)
|
||
curl -fsSL "https://nodejs.org/dist/index.json" 2>/dev/null | python3 -c "import json,sys; print(json.load(sys.stdin)[0]['version'])" 2>/dev/null || echo "v24.18.0"
|
||
;;
|
||
*)
|
||
echo "v${1#v}"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
direct_install_binary() {
|
||
RESOLVED="$1"
|
||
DEST="$NVM_DIR/versions/node/${RESOLVED}"
|
||
TMP="/tmp/node-dl-$$"
|
||
rm -rf "$TMP" "$DEST"
|
||
mkdir -p "$TMP"
|
||
if [ -f /etc/alpine-release ]; then
|
||
# Node 官方仅 glibc;Alpine musl 走 unofficial-builds // Logan.Li
|
||
URLS="https://unofficial-builds.nodejs.org/download/release/${RESOLVED}/node-${RESOLVED}-linux-x64-musl.tar.xz"
|
||
else
|
||
URLS="${NODE_MIRROR}/${RESOLVED}/node-${RESOLVED}-linux-x64.tar.xz https://nodejs.org/dist/${RESOLVED}/node-${RESOLVED}-linux-x64.tar.xz"
|
||
fi
|
||
for URL in $URLS; do
|
||
echo "[Node.js] Downloading $URL"
|
||
rm -rf "$TMP"/* 2>/dev/null || true
|
||
if curl -fsSL -L "$URL" | tar -xJ -C "$TMP" 2>/dev/null; then
|
||
SUB=$(find "$TMP" -mindepth 1 -maxdepth 1 -type d | head -1)
|
||
if [ -n "$SUB" ] && [ -x "$SUB/bin/node" ]; then
|
||
mv "$SUB" "$DEST"
|
||
rm -rf "$TMP"
|
||
echo "[Node.js] Installed $RESOLVED"
|
||
return 0
|
||
fi
|
||
fi
|
||
echo "[Node.js] Failed: $URL"
|
||
done
|
||
rm -rf "$TMP"
|
||
return 1
|
||
}
|
||
|
||
RESOLVED=$(resolve_version "$NODE_VERSION")
|
||
[ -n "$RESOLVED" ] || { echo "[Node.js] cannot resolve version for $NODE_VERSION"; exit 1; }
|
||
echo "[Node.js] Target version: $RESOLVED"
|
||
direct_install_binary "$RESOLVED" || { echo "[Node.js] binary install failed"; exit 1; }
|
||
|
||
INST="$RESOLVED"
|
||
mkdir -p /usr/local/bin
|
||
ln -sf "$NVM_DIR/versions/node/${INST}/bin/node" /usr/local/bin/node
|
||
ln -sf "$NVM_DIR/versions/node/${INST}/bin/npm" /usr/local/bin/npm
|
||
ln -sf "$NVM_DIR/versions/node/${INST}/bin/npx" /usr/local/bin/npx
|
||
"$NVM_DIR/versions/node/${INST}/bin/npm" config set registry https://registry.npmmirror.com
|
||
echo "[Node.js] Installed: $(/usr/local/bin/node --version) / npm $("$NVM_DIR/versions/node/${INST}/bin/npm" --version)"
|
||
`,
|
||
SortOrder: 5,
|
||
},
|
||
// ──── Git — 版本控制(懒加载, U4 镜像瘦身)// Logan.Li ────
|
||
{
|
||
Name: "git",
|
||
DisplayName: "Git",
|
||
Description: "版本控制工具,流水线代码拉取使用(首次使用自动安装)",
|
||
Category: "build",
|
||
InstallMethod: ToolLazy,
|
||
BinaryName: "git",
|
||
InstallPath: "/usr/bin/git",
|
||
CheckCommand: "git --version 2>/dev/null",
|
||
InstallScript: `apk add --no-cache git`,
|
||
SortOrder: 6,
|
||
},
|
||
// ──── Docker CLI — 容器构建(懒加载, U4 镜像瘦身)// Logan.Li ────
|
||
{
|
||
Name: "docker-cli",
|
||
DisplayName: "Docker CLI",
|
||
Description: "Docker 命令行工具,流水线镜像构建/推送使用(首次使用自动安装)",
|
||
Category: "deploy",
|
||
InstallMethod: ToolLazy,
|
||
BinaryName: "docker",
|
||
InstallPath: "/usr/bin/docker",
|
||
CheckCommand: "docker --version 2>/dev/null",
|
||
InstallScript: `apk add --no-cache docker-cli`,
|
||
SortOrder: 7,
|
||
},
|
||
}
|
||
}
|