feat: Agent批量升级 + 版本号注入 + 服务器凭证下拉关联
- Dockerfile: ARG VERSION/BUILD_TIME 通过 ldflags 注入 agent+backend 二进制 - run.sh: 自动从 git tag 获取版本号 - docker-compose: build args 传递 VERSION/BUILD_TIME - backend: BatchUpgradeAgent SSH下载新二进制+重启, /agent/bin 静态文件服务 - frontend: 监控大屏添加批量升级按钮 (闪电图标) - frontend: 服务器编辑/添加表单改为凭证下拉选择器 - frontend: ServerForm 加载 /credentials 列表, 选择后自动填充用户名/认证方式
This commit is contained in:
1 parent
228b6b52f9
commit
ed08ea255e
9 files changed
+253
-52
No files matched your search
+10
-6
@@ -6,6 +6,10 @@
|
||||
# 署名 Logan.Li
|
||||
# ============================================================
|
||||
|
||||
# 构建参数 — 版本号通过 git tag 或环境变量注入
|
||||
ARG VERSION=dev
|
||||
ARG BUILD_TIME=unknown
|
||||
|
||||
# ==================== Stage 1: Backend Builder ====================
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
@@ -26,9 +30,9 @@ RUN go mod download
|
||||
# 复制后端源码
|
||||
COPY backend/ ./
|
||||
|
||||
# 构建后端二进制
|
||||
# 构建后端二进制(注入版本号)
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
||||
-ldflags="-w -s" \
|
||||
-ldflags="-w -s -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME}" \
|
||||
-o aiops ./cmd/
|
||||
|
||||
# ==================== Stage 2: Agent Builder ====================
|
||||
@@ -46,10 +50,10 @@ RUN go mod download
|
||||
# 复制 agent 源码
|
||||
COPY agent/ ./
|
||||
|
||||
# 交叉编译三个平台的 agent 二进制
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/aiops-agent-linux-amd64 . && \
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o bin/aiops-agent-linux-arm64 . && \
|
||||
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o bin/aiops-agent-darwin-arm64 .
|
||||
# 交叉编译三个平台的 agent 二进制(注入版本号)
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=${VERSION} -X main.buildTime=${BUILD_TIME}" -o bin/aiops-agent-linux-amd64 . && \
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w -X main.version=${VERSION} -X main.buildTime=${BUILD_TIME}" -o bin/aiops-agent-linux-arm64 . && \
|
||||
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w -X main.version=${VERSION} -X main.buildTime=${BUILD_TIME}" -o bin/aiops-agent-darwin-arm64 .
|
||||
|
||||
# ==================== Stage 3: Runtime ====================
|
||||
FROM alpine:latest
|
||||
|
||||
@@ -377,6 +377,78 @@ func (h *AgentInstallHandler) BatchUninstallAgent(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// BatchUpgradeAgent 批量升级 Agent 到最新版本(SSH下载新二进制 + 重启服务)
|
||||
// POST /api/v1/agent/batch-upgrade
|
||||
func (h *AgentInstallHandler) BatchUpgradeAgent(c *gin.Context) {
|
||||
var req struct {
|
||||
ServerIDs []uint `json:"server_ids"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil || len(req.ServerIDs) == 0 {
|
||||
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "请提供要升级的服务器 ID 列表"})
|
||||
return
|
||||
}
|
||||
|
||||
serverURL := fmt.Sprintf("http://%s", c.Request.Host)
|
||||
|
||||
// 异步执行:立即返回,后台逐台升级
|
||||
go func() {
|
||||
successCount := 0
|
||||
for _, sid := range req.ServerIDs {
|
||||
var server models.Server
|
||||
if err := h.db.First(&server, sid).Error; err != nil {
|
||||
log.Printf("[BatchUpgrade] 服务器 %d 不存在,跳过", sid)
|
||||
continue
|
||||
}
|
||||
if server.Username == "" || (server.Password == "" && server.SSHKey == "") {
|
||||
log.Printf("[BatchUpgrade] %s 无SSH凭据,跳过", server.Hostname)
|
||||
continue
|
||||
}
|
||||
|
||||
// 检测架构
|
||||
client, err := sshDial(server)
|
||||
if err != nil {
|
||||
log.Printf("[BatchUpgrade] %s SSH连接失败: %v", server.Hostname, err)
|
||||
continue
|
||||
}
|
||||
|
||||
archOut, _ := runSSHCommand(client, "uname -m")
|
||||
binaryFile := "aiops-agent-linux-amd64"
|
||||
if len(archOut) > 0 && (contains(archOut, "aarch64") || contains(archOut, "arm64")) {
|
||||
binaryFile = "aiops-agent-linux-arm64"
|
||||
}
|
||||
|
||||
// 下载新二进制 + 重启服务
|
||||
upgradeScript := fmt.Sprintf(
|
||||
`curl -fsSL -o /tmp/aiops-agent %s/agent/bin/%s && chmod +x /tmp/aiops-agent && systemctl stop aiops-agent 2>/dev/null; mv /tmp/aiops-agent /usr/local/bin/aiops-agent && systemctl start aiops-agent && echo "UPGRADE_OK"`,
|
||||
serverURL, binaryFile,
|
||||
)
|
||||
|
||||
out, err := runSSHCommand(client, upgradeScript)
|
||||
client.Close()
|
||||
|
||||
if err != nil || !contains(out, "UPGRADE_OK") {
|
||||
log.Printf("[BatchUpgrade] %s 升级失败: output=%s err=%v", server.Hostname, out, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 更新版本号
|
||||
h.db.Model(&server).Updates(map[string]interface{}{
|
||||
"agent_version": "latest",
|
||||
"last_check_at": time.Now(),
|
||||
})
|
||||
log.Printf("[BatchUpgrade] %s Agent 升级成功", server.Hostname)
|
||||
successCount++
|
||||
}
|
||||
log.Printf("[BatchUpgrade] 批量升级完成: %d/%d 成功", successCount, len(req.ServerIDs))
|
||||
}()
|
||||
|
||||
c.JSON(http.StatusOK, models.Response{
|
||||
Code: 200,
|
||||
Message: fmt.Sprintf("已提交异步升级任务,共 %d 台主机,正在后台执行…", len(req.ServerIDs)),
|
||||
Data: gin.H{"total": len(req.ServerIDs), "async": true},
|
||||
})
|
||||
}
|
||||
|
||||
// RemoteExec 直连 SSH 执行命令(即时返回,无轮询)
|
||||
// POST /api/v1/agent/exec
|
||||
func (h *AgentInstallHandler) RemoteExec(c *gin.Context) {
|
||||
|
||||
@@ -455,8 +455,12 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
|
||||
// Agent 安装/卸载
|
||||
agentQuery.POST("/uninstall", agentInstallHandler.UninstallAgent)
|
||||
agentQuery.POST("/batch-uninstall", agentInstallHandler.BatchUninstallAgent)
|
||||
agentQuery.POST("/batch-upgrade", agentInstallHandler.BatchUpgradeAgent)
|
||||
}
|
||||
|
||||
// Agent 二进制下载(无需鉴权,Agent 升级时使用)
|
||||
router.Static("/agent/bin", "/app/agent/bin")
|
||||
|
||||
// AI 智能助手 - LLM 配置 + 对话代理(OpenAI 兼容) // Logan.Li
|
||||
llmHandler := handlers.NewLLMHandler(db)
|
||||
aiopsGroup := authorized.Group("/aiops")
|
||||
|
||||
Reference in new issue
Block a user