Files
aiops/backend/controller/credential_assign.go
T
LoganandClaude 0b2e43ea9e feat(llm): 大模型双协议(OpenAI+Anthropic)接入 + SSH凭证修复 + 容量预测AI解读
后端双协议: 新增 anthropic.go(Complete/Stream/工具转换) + client.go 工厂按 Protocol 路由; llm.Client 加 Stream; llm_chat 三方法收敛复用 llm.Client; resolveProtocol 按 provider 路由; Agent CLI 注入协议。编码套餐(GLM-5.2/Kimi/MiMo/Anthropic)走 Anthropic /v1/messages。

SSH凭证修复: applyCredential 正确解析凭证 JSON 的 private_key(旧实现把整个 JSON 当私钥 → ssh.ParsePrivateKey 失败 → ssh-key 登录不通); AssignCredential/批量导入/单台 CRUD 三处统一; 单台补齐 credential_id 字段(原被忽略)。

容量预测: 新增 AI 深度解读(buildCapacityInsightPrompt + PredictiveCapacityTab 按钮, 复用 aiApi.chat)。

其他: DeepSeek 模型名更新为 deepseek-v4-flash/pro; 智能助手去掉重复模型配置按钮; LLMConfig 精简生成参数(Claude Code 式)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-28 22:37:46 +08:00

83 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package controller
import (
"encoding/json"
"net/http"
"strconv"
"ezops/model"
"github.com/gin-gonic/gin"
)
// AssignCredential 将凭据分配给服务器(解密凭据并写入 password/ssh_key) // Logan.Li
func (h *CredentialHandler) AssignCredential(c *gin.Context) {
serverID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "无效的服务器ID"})
return
}
var req struct {
CredentialID uint `json:"credential_id"`
}
if err := c.ShouldBindJSON(&req); err != nil || req.CredentialID == 0 {
c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "请选择凭据"})
return
}
var cred model.Credential
if err := h.db.First(&cred, req.CredentialID).Error; err != nil {
c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "凭据不存在"})
return
}
plain, err := h.crypt.Decrypt(cred.Content)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "凭据解密失败"})
return
}
var server model.Server
if err := h.db.First(&server, serverID).Error; err != nil {
c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "服务器不存在"})
return
}
applyCredential(cred, plain, &server)
if err := h.db.Save(&server).Error; err != nil {
c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "分配失败: " + err.Error()})
return
}
c.JSON(http.StatusOK, model.Response{Code: 200, Message: "凭据已关联"})
}
// applyCredential 将解密后的明文 plain 填充到 server 认证字段(统一入口,避免 plain JSON 误用) // Logan.Li
// ssh 凭证 plain 是 JSON {"private_key":...,"ssh_user":...,"ssh_port":...},须解析出 private_key(旧实现直接把
// 整个 JSON 当私钥,导致 ssh.ParsePrivateKey 失败 → ssh-key 登录不通);其余类型 plain 即密码。
// 供 AssignCredential / 单台服务器 CRUD / 批量导入 三处复用。
func applyCredential(cred model.Credential, plain string, server *model.Server) {
if cred.SecretType == "ssh" {
privateKey := plain
var sshc model.SSHSecretContent
if json.Unmarshal([]byte(plain), &sshc) == nil && sshc.PrivateKey != "" {
privateKey = sshc.PrivateKey
if sshc.SSHUser != "" {
server.Username = sshc.SSHUser
}
if sshc.SSHPort > 0 {
server.Port = sshc.SSHPort
}
}
server.SSHKey = privateKey
server.AuthType = "key"
server.Password = ""
} else {
server.Password = plain
server.AuthType = "password"
server.SSHKey = ""
}
}