Files
aiops/backend/controller/agent_cli_kubernetes.go
T
LoganandClaude 76ec9387f0 feat(rdp): 新增 RDP 远程桌面/SMB/账单同步能力 + 清理编译产物
主要变更:
- RDP 远程桌面:新增 backend/pkg/rdp(RDP 引擎 + credssp/display/rle/trace)、
  backend/controller/rdp*(连接/凭证/文件/会话/实时)、frontend RDP 组件与 API
- Windows SMB 文件传输:backend/pkg/winsmb
- 云账单同步:backend/pkg/billingsync + billing_sync/aliyun_billing,前端账单详情
- Agent CLI Kubernetes 工具:kubernetes_action/get、pod_execute/logs
- 服务器导入助手:server_import_helpers、ImportCredentialSettings
- 国际化与组件重构(cloud/deploy/monitor/server/system 等多模块)
- 清理编译产物二进制:移除 backend/server、backend/agent/bin/aiops-agent-*
- .gitignore:新增 backend/agent/ 与 .cache/(避免 334MB go-build 缓存误入库)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-04 01:50:36 +08:00

111 lines
3.4 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.
// agent_cli_kubernetes.go - Agent CLI Kubernetes 模式 WebSocket 支持 // Logan.Li
package controller
import (
"fmt"
"strings"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"ezops/model"
k8sclient "ezops/pkg/kubernetesclient"
)
// kubernetesAgentContext Kubernetes 模式运行上下文 // Logan.Li
type kubernetesAgentContext struct {
cluster model.KubernetesCluster
client *k8sclient.Client
namespace string
podName string
container string
}
// parseKubernetesWSParams 从 WS 查询参数解析 Kubernetes 目标 // Logan.Li
func parseKubernetesWSParams(c *gin.Context) (clusterCode, namespace, podName, container string) {
clusterCode = strings.TrimSpace(c.Query("cluster"))
namespace = strings.TrimSpace(c.Query("namespace"))
podName = strings.TrimSpace(c.Query("pod"))
container = strings.TrimSpace(c.Query("container"))
return
}
// loadKubernetesAgentContext 加载集群客户端并预检 // Logan.Li
func loadKubernetesAgentContext(db *gorm.DB, clusterCode, namespace, podName string) (*kubernetesAgentContext, error) {
if clusterCode == "" {
return nil, fmt.Errorf("缺少 cluster 参数")
}
if namespace == "" {
return nil, fmt.Errorf("缺少 namespace 参数")
}
var cluster model.KubernetesCluster
if err := db.Where("code = ?", clusterCode).First(&cluster).Error; err != nil {
return nil, fmt.Errorf("集群不存在: %s", clusterCode)
}
client, err := buildK8sClient(&cluster)
if err != nil {
return nil, fmt.Errorf("集群连接失败: %w", err)
}
if _, err := client.ListNamespaces(); err != nil {
return nil, fmt.Errorf("集群 API 不可达: %w", err)
}
if podName != "" {
pods, err := client.ListPods()
if err != nil {
return nil, fmt.Errorf("获取 Pod 列表失败: %w", err)
}
found := false
for _, p := range pods.Items {
if p.Metadata.Namespace == namespace && p.Metadata.Name == podName {
found = true
break
}
}
if !found {
return nil, fmt.Errorf("Pod %s/%s 不存在", namespace, podName)
}
}
return &kubernetesAgentContext{
cluster: cluster, client: client,
namespace: namespace, podName: podName,
}, nil
}
// buildKubernetesTargetInfo 构建注入 Prompt 的集群上下文摘要 // Logan.Li
func buildKubernetesTargetInfo(ctx *kubernetesAgentContext) string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("集群: %s(code=%s)| Namespace: %s", ctx.cluster.Name, ctx.cluster.Code, ctx.namespace))
if ctx.podName != "" {
sb.WriteString(fmt.Sprintf(" | Pod: %s", ctx.podName))
if pods, err := ctx.client.ListPods(); err == nil {
for _, p := range pods.Items {
if p.Metadata.Namespace == ctx.namespace && p.Metadata.Name == ctx.podName {
image := ""
if len(p.Spec.Containers) > 0 {
image = p.Spec.Containers[0].Image
if ctx.container == "" {
ctx.container = p.Spec.Containers[0].Name
}
}
sb.WriteString(fmt.Sprintf(" | 状态: %s | 节点: %s | 镜像: %s", p.Status.Phase, p.Spec.NodeName, image))
break
}
}
}
} else {
sb.WriteString(" | Pod: (未选定,集群/命名空间级任务)")
}
if ctx.container != "" {
sb.WriteString(fmt.Sprintf(" | 容器: %s", ctx.container))
}
return sb.String()
}
// kubernetesEvolveHostKey Evolver 记忆分桶键 // Logan.Li
func kubernetesEvolveHostKey(ctx *kubernetesAgentContext) string {
base := fmt.Sprintf("kubernetes://%s/%s", ctx.cluster.Code, ctx.namespace)
if ctx.podName != "" {
return base + "/" + ctx.podName
}
return base
}