Files
aiops/backend/internal/api/handlers/kubernetes.go
T
attacker 4dd5e10b46 refactor(k8s): Q2 kubernetes.go 模块化拆分 — 4204行单文件→12个域文件
将 handlers/kubernetes.go (4204行/134函数) 按业务域拆分为:
- kubernetes.go (106L): struct + constructor + 共享helpers
- k8s_cluster.go (642L): 集群CRUD + 同步 + RBAC
- k8s_workload.go (696L): Deployment/STS/DS/ReplicaSet操作
- k8s_pod.go (653L): Pod日志/终端/exec/指标
- k8s_pod_files.go (206L): Pod文件浏览/上传/下载
- k8s_resource.go (351L): Service/Ingress/ConfigMap/Secret/PVC/Topology
- k8s_hpa_cronjob.go (384L): HPA + CronJob
- k8s_yaml.go (213L): YAML get/update/delete/apply
- k8s_namespace.go (305L): Namespace CRUD
- k8s_events.go (207L): 事件列表+聚合
- k8s_node.go (428L): Node详情+资源分配
- k8s_compare.go (146L): 多集群对比

验收: go build零错误, 425条路由不变, 26个K8s API端点回归测试全通过
2026-06-25 04:51:21 +08:00

107 lines
3.0 KiB
Go

package handlers
import (
"fmt"
"gorm.io/gorm"
"strconv"
"time"
"ezops/internal/models"
k8sclient "ezops/pkg/kubernetesclient"
"github.com/gin-gonic/gin"
)
// KubernetesHandler K8s处理器
type KubernetesHandler struct {
db *gorm.DB
}
// NewKubernetesHandler 创建K8s处理器
func NewKubernetesHandler(db *gorm.DB) *KubernetesHandler {
return &KubernetesHandler{db: db}
}
// ============================================================================
// Shared helpers (used by all k8s_*.go files in this package)
// ============================================================================
func (h *KubernetesHandler) resolveClusterCode(code string) int {
if code == "" {
return 0
}
var cluster models.KubernetesCluster
if err := h.db.Where("code = ?", code).First(&cluster).Error; err != nil {
return 0
}
return int(cluster.ID)
}
// formatAge converts a K8s creationTimestamp (RFC3339) to a human-readable relative age
func formatAge(creationTimestamp string) string {
if creationTimestamp == "" {
return "-"
}
t, err := time.Parse(time.RFC3339, creationTimestamp)
if err != nil {
return creationTimestamp
}
d := time.Since(t)
switch {
case d < time.Minute:
return fmt.Sprintf("%ds", int(d.Seconds()))
case d < time.Hour:
return fmt.Sprintf("%dm", int(d.Minutes()))
case d < 24*time.Hour:
return fmt.Sprintf("%dh", int(d.Hours()))
case d < 30*24*time.Hour:
return fmt.Sprintf("%dd", int(d.Hours()/24))
case d < 365*24*time.Hour:
return fmt.Sprintf("%dM", int(d.Hours()/(24*30)))
default:
return fmt.Sprintf("%dy", int(d.Hours()/(24*365)))
}
}
// getK8sClientByCode resolves cluster by code, falls back to ID
func (h *KubernetesHandler) getK8sClientByCode(c *gin.Context) (*k8sclient.Client, *models.KubernetesCluster, error) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 {
// 支持 :clusterCode 或 :id 参数
code := c.Param("clusterCode")
if code == "" {
code = c.Param("id")
}
clusterID = h.resolveClusterCode(code)
}
if clusterID == 0 {
return nil, nil, fmt.Errorf("cluster not found")
}
return h.getK8sClient(clusterID)
}
// ============================================================================
// NS wrappers — read namespace from path (Kuboard-style routes)
// ============================================================================
func (h *KubernetesHandler) getK8sClient(clusterID int) (*k8sclient.Client, *models.KubernetesCluster, error) {
var cluster models.KubernetesCluster
if err := h.db.First(&cluster, clusterID).Error; err != nil {
return nil, nil, fmt.Errorf("cluster not found")
}
if cluster.KubeConfig == "" {
return nil, nil, fmt.Errorf("no kubeconfig")
}
client, err := k8sclient.NewClient(cluster.KubeConfig)
if err != nil {
return nil, nil, err
}
return client, &cluster, nil
}
// ============================================================================
// PVC (存储) handlers
// ============================================================================
// ListPVCsNS lists PersistentVolumeClaims in a namespace (code-based)