refactor: 全局重命名 k8s → kubernetes (前后端+路由+表名+文件)

后端:
  - pkg/k8sclient → pkg/kubernetesclient
  - models/k8s.go → models/kubernetes.go
  - handlers/k8s.go → handlers/kubernetes.go
  - K8sCluster/K8sNode/.. → KubernetesCluster/KubernetesNode/..
  - K8sHandler → KubernetesHandler
  - 路由: /k8s-clusters → /kubernetes-clusters
  - 路由: /k8s/:code/namespace/:ns/... → /kubernetes/:code/namespace/:ns/... (Kuboard风格)
  - 表前缀: container_k8s_ → container_kubernetes_

前端:
  - components/k8s/ → components/kubernetes/
  - K8sClusters → KubernetesClusters
  - K8sWorkloads → KubernetesWorkloads
  - K8sNodes → KubernetesNodes
  - k8sApi → kubernetesApi
  - 路由前缀: /k8s/ → /kubernetes/

测试验证:
✅ /kubernetes/k8s-cluster-liren/namespace/kube-system/deployments → 3 items
✅ /kubernetes/k8s-cluster-liren/namespace/kube-system/pods → 7 items
✅ /kubernetes/k8s-cluster-liren/namespace/kube-system/services → 4 items
✅ /kubernetes/k8s-cluster-liren/namespace/kube-system/configmaps → 6 items
✅ /kubernetes/k8s-cluster-liren/namespace/kube-system/secrets → 1 item
✅ /kubernetes/k8s-cluster-liren/namespaces → 4 items
This commit is contained in:
attacker committed 2026-06-19 08:10:12 +00:00
1 parent f7b667b878
commit cac1414917
27 files changed
+779 -284

No files matched your search

+1 -1
View File
@@ -134,7 +134,7 @@ func (h *AuditHandler) GetAuditModules(c *gin.Context) {
modules := []map[string]string{
{"value": "user", "label": "用户管理"},
{"value": "server", "label": "服务器管理"},
{"value": "k8s", "label": "Kubernetes"},
{"value": "kubernetes", "label": "Kubernetes"},
{"value": "alert", "label": "监控告警"},
{"value": "pipeline", "label": "应用发布"},
{"value": "automation", "label": "自动化运维"},
+8 -8
View File
@@ -53,16 +53,16 @@ func (h *DashboardHandler) GetStats(c *gin.Context) {
stats.ServerStats = serverStats
// K8s集群统计
var k8sStats models.K8sClusterStats
h.db.Model(&models.K8sCluster{}).Count(&k8sStats.Total)
h.db.Model(&models.K8sCluster{}).Where("status = ?", "healthy").Count(&k8sStats.Healthy)
h.db.Model(&models.K8sCluster{}).Where("status = ?", "warning").Count(&k8sStats.Warning)
h.db.Model(&models.K8sCluster{}).Where("status = ?", "error").Count(&k8sStats.Error)
var k8sStats models.KubernetesClusterStats
h.db.Model(&models.KubernetesCluster{}).Count(&k8sStats.Total)
h.db.Model(&models.KubernetesCluster{}).Where("status = ?", "healthy").Count(&k8sStats.Healthy)
h.db.Model(&models.KubernetesCluster{}).Where("status = ?", "warning").Count(&k8sStats.Warning)
h.db.Model(&models.KubernetesCluster{}).Where("status = ?", "error").Count(&k8sStats.Error)
var totalNodes, totalPods, totalServices int64
h.db.Model(&models.K8sNode{}).Count(&totalNodes)
h.db.Model(&models.K8sPod{}).Count(&totalPods)
h.db.Model(&models.K8sService{}).Count(&totalServices)
h.db.Model(&models.KubernetesNode{}).Count(&totalNodes)
h.db.Model(&models.KubernetesPod{}).Count(&totalPods)
h.db.Model(&models.KubernetesService{}).Count(&totalServices)
k8sStats.TotalNodes = totalNodes
k8sStats.TotalPods = totalPods
k8sStats.TotalServices = totalServices
@@ -11,20 +11,20 @@ import (
"time"
"ezops/internal/models"
"ezops/pkg/k8sclient"
"ezops/pkg/kubernetesclient"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// K8sHandler K8s处理器
type K8sHandler struct {
// KubernetesHandler K8s处理器
type KubernetesHandler struct {
db *gorm.DB
}
// NewK8sHandler 创建K8s处理器
func NewK8sHandler(db *gorm.DB) *K8sHandler {
return &K8sHandler{db: db}
// NewKubernetesHandler 创建K8s处理器
func NewKubernetesHandler(db *gorm.DB) *KubernetesHandler {
return &KubernetesHandler{db: db}
}
// ListClusters 获取集群列表
@@ -36,15 +36,15 @@ func NewK8sHandler(db *gorm.DB) *K8sHandler {
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} models.Response{data=models.ListResponse}
// @Router /k8s-clusters [get]
func (h *K8sHandler) ListClusters(c *gin.Context) {
// @Router /kubernetes-clusters [get]
func (h *KubernetesHandler) ListClusters(c *gin.Context) {
var query models.PageQuery
c.ShouldBindQuery(&query)
var total int64
h.db.Model(&models.K8sCluster{}).Count(&total)
h.db.Model(&models.KubernetesCluster{}).Count(&total)
var clusters []models.K8sCluster
var clusters []models.KubernetesCluster
h.db.Offset(query.GetOffset()).Limit(query.GetLimit()).Find(&clusters)
c.JSON(http.StatusOK, models.Response{
@@ -64,12 +64,12 @@ func (h *K8sHandler) ListClusters(c *gin.Context) {
// @Produce json
// @Security Bearer
// @Param id path int true "集群ID"
// @Success 200 {object} models.Response{data=models.K8sCluster}
// @Router /k8s-clusters/{id} [get]
func (h *K8sHandler) GetCluster(c *gin.Context) {
// @Success 200 {object} models.Response{data=models.KubernetesCluster}
// @Router /kubernetes-clusters/{id} [get]
func (h *KubernetesHandler) GetCluster(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var cluster models.K8sCluster
var cluster models.KubernetesCluster
if err := h.db.First(&cluster, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{
Code: 404,
@@ -92,11 +92,11 @@ func (h *K8sHandler) GetCluster(c *gin.Context) {
// @Accept json
// @Produce json
// @Security Bearer
// @Param request body models.CreateK8sClusterRequest true "创建请求"
// @Success 200 {object} models.Response{data=models.K8sCluster}
// @Router /k8s-clusters [post]
func (h *K8sHandler) CreateCluster(c *gin.Context) {
var req models.CreateK8sClusterRequest
// @Param request body models.CreateKubernetesClusterRequest true "创建请求"
// @Success 200 {object} models.Response{data=models.KubernetesCluster}
// @Router /kubernetes-clusters [post]
func (h *KubernetesHandler) CreateCluster(c *gin.Context) {
var req models.CreateKubernetesClusterRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{
Code: 400,
@@ -105,7 +105,7 @@ func (h *K8sHandler) CreateCluster(c *gin.Context) {
return
}
cluster := models.K8sCluster{
cluster := models.KubernetesCluster{
Name: req.Name,
Code: req.Code,
Version: req.Version,
@@ -141,10 +141,10 @@ func (h *K8sHandler) CreateCluster(c *gin.Context) {
// @Produce json
// @Security Bearer
// @Param id path int true "集群ID"
// @Param request body models.CreateK8sClusterRequest true "更新请求"
// @Success 200 {object} models.Response{data=models.K8sCluster}
// @Router /k8s-clusters/{id} [put]
func (h *K8sHandler) UpdateCluster(c *gin.Context) {
// @Param request body models.CreateKubernetesClusterRequest true "更新请求"
// @Success 200 {object} models.Response{data=models.KubernetesCluster}
// @Router /kubernetes-clusters/{id} [put]
func (h *KubernetesHandler) UpdateCluster(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
// 用 map 接收,避免 binding:"required" 校验 // Logan.Li
@@ -157,7 +157,7 @@ func (h *K8sHandler) UpdateCluster(c *gin.Context) {
return
}
var cluster models.K8sCluster
var cluster models.KubernetesCluster
if err := h.db.First(&cluster, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{
Code: 404,
@@ -219,10 +219,10 @@ func (h *K8sHandler) UpdateCluster(c *gin.Context) {
}
// GetClusterDetail 返回集群完整信息(含 token/kube_config,供编辑回填) // Logan.Li
func (h *K8sHandler) GetClusterDetail(c *gin.Context) {
func (h *KubernetesHandler) GetClusterDetail(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var cluster models.K8sCluster
var cluster models.KubernetesCluster
if err := h.db.First(&cluster, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{
Code: 404,
@@ -264,11 +264,11 @@ func (h *K8sHandler) GetClusterDetail(c *gin.Context) {
// @Security Bearer
// @Param id path int true "集群ID"
// @Success 200 {object} models.Response
// @Router /k8s-clusters/{id} [delete]
func (h *K8sHandler) DeleteCluster(c *gin.Context) {
// @Router /kubernetes-clusters/{id} [delete]
func (h *KubernetesHandler) DeleteCluster(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
if err := h.db.Delete(&models.K8sCluster{}, id).Error; err != nil {
if err := h.db.Delete(&models.KubernetesCluster{}, id).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{
Code: 500,
Message: "删除失败",
@@ -289,9 +289,9 @@ func (h *K8sHandler) DeleteCluster(c *gin.Context) {
// @Produce json
// @Security Bearer
// @Param id path int true "集群ID"
// @Success 200 {object} models.Response{data=[]models.K8sNode}
// @Router /k8s-clusters/{id}/nodes [get]
func (h *K8sHandler) ListNodes(c *gin.Context) {
// @Success 200 {object} models.Response{data=[]models.KubernetesNode}
// @Router /kubernetes-clusters/{id}/nodes [get]
func (h *KubernetesHandler) ListNodes(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
client, _, err := h.getK8sClient(clusterID)
@@ -363,9 +363,9 @@ func (h *K8sHandler) ListNodes(c *gin.Context) {
// @Security Bearer
// @Param id path int true "集群ID"
// @Param namespace query string false "命名空间"
// @Success 200 {object} models.Response{data=[]models.K8sPod}
// @Router /k8s-clusters/{id}/pods [get]
func (h *K8sHandler) ListPods(c *gin.Context) {
// @Success 200 {object} models.Response{data=[]models.KubernetesPod}
// @Router /kubernetes-clusters/{id}/pods [get]
func (h *KubernetesHandler) ListPods(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Query("namespace")
@@ -423,9 +423,9 @@ func (h *K8sHandler) ListPods(c *gin.Context) {
// @Security Bearer
// @Param id path int true "集群ID"
// @Param namespace query string false "命名空间"
// @Success 200 {object} models.Response{data=[]models.K8sDeployment}
// @Router /k8s-clusters/{id}/deployments [get]
func (h *K8sHandler) ListDeployments(c *gin.Context) {
// @Success 200 {object} models.Response{data=[]models.KubernetesDeployment}
// @Router /kubernetes-clusters/{id}/deployments [get]
func (h *KubernetesHandler) ListDeployments(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Query("namespace")
@@ -477,9 +477,9 @@ func (h *K8sHandler) ListDeployments(c *gin.Context) {
// @Security Bearer
// @Param id path int true "集群ID"
// @Param namespace query string false "命名空间"
// @Success 200 {object} models.Response{data=[]models.K8sService}
// @Router /k8s-clusters/{id}/services [get]
func (h *K8sHandler) ListServices(c *gin.Context) {
// @Success 200 {object} models.Response{data=[]models.KubernetesService}
// @Router /kubernetes-clusters/{id}/services [get]
func (h *KubernetesHandler) ListServices(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Query("namespace")
@@ -525,9 +525,9 @@ func (h *K8sHandler) ListServices(c *gin.Context) {
// @Security Bearer
// @Param id path int true "集群ID"
// @Param namespace query string false "命名空间"
// @Success 200 {object} models.Response{data=[]models.K8sIngress}
// @Router /k8s-clusters/{id}/ingresses [get]
func (h *K8sHandler) ListIngresses(c *gin.Context) {
// @Success 200 {object} models.Response{data=[]models.KubernetesIngress}
// @Router /kubernetes-clusters/{id}/ingresses [get]
func (h *KubernetesHandler) ListIngresses(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Query("namespace")
@@ -570,7 +570,7 @@ func (h *K8sHandler) ListIngresses(c *gin.Context) {
}
// GetTopology 获取集群拓扑布局 // Logan.Li
func (h *K8sHandler) GetTopology(c *gin.Context) {
func (h *KubernetesHandler) GetTopology(c *gin.Context) {
clusterID := c.Param("id")
var layout models.TopologyLayout
result := h.db.Where("cluster_id = ?", clusterID).First(&layout)
@@ -582,7 +582,7 @@ func (h *K8sHandler) GetTopology(c *gin.Context) {
}
// SaveTopology 保存集群拓扑布局 // Logan.Li
func (h *K8sHandler) SaveTopology(c *gin.Context) {
func (h *KubernetesHandler) SaveTopology(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
var req struct {
LayoutData string `json:"layout_data"`
@@ -607,10 +607,10 @@ func (h *K8sHandler) SaveTopology(c *gin.Context) {
// SyncCluster 同步集群资源(连接真实K8s API拉取数据)
func (h *K8sHandler) SyncCluster(c *gin.Context) {
func (h *KubernetesHandler) SyncCluster(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var cluster models.K8sCluster
var cluster models.KubernetesCluster
if err := h.db.First(&cluster, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{Code: 404, Message: "集群不存在"})
return
@@ -632,7 +632,7 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
// Sync nodes
if nodes, err := client.ListNodes(); err == nil {
// Use raw SQL for reliability (avoid GORM soft-delete / auto-timestamp issues)
h.db.Exec("DELETE FROM k8s_nodes WHERE cluster_id = ?", cluster.ID)
h.db.Exec("DELETE FROM kubernetes_nodes WHERE cluster_id = ?", cluster.ID)
for _, n := range nodes.Items {
role := "worker"
if _, ok := n.Metadata.Labels["node-role.kubernetes.io/master"]; ok {
@@ -656,7 +656,7 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
}
labelsJSON, _ := json.Marshal(n.Metadata.Labels)
now := time.Now()
err2 := h.db.Exec(`INSERT INTO k8s_nodes (cluster_id, name, ip, role, status, os, kubelet_version, cpu, memory, max_pods, labels, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
err2 := h.db.Exec(`INSERT INTO kubernetes_nodes (cluster_id, name, ip, role, status, os, kubelet_version, cpu, memory, max_pods, labels, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
cluster.ID, n.Metadata.Name, ip, role, nodeStatus, n.Status.NodeInfo.OSImage, n.Status.NodeInfo.KubeletVersion,
parseIntResource(n.Status.Capacity["cpu"]), parseMemResource(n.Status.Capacity["memory"]), parseIntResource(n.Status.Capacity["pods"]),
string(labelsJSON), now, now).Error
@@ -672,7 +672,7 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
// Sync pods
if pods, err := client.ListPods(); err == nil {
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.K8sPod{})
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.KubernetesPod{})
for _, p := range pods.Items {
image := ""
if len(p.Spec.Containers) > 0 {
@@ -683,7 +683,7 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
restarts = p.Status.ContainerStatuses[0].RestartCount
}
labelsJSON, _ := json.Marshal(p.Metadata.Labels)
h.db.Create(&models.K8sPod{
h.db.Create(&models.KubernetesPod{
ClusterID: cluster.ID,
Namespace: p.Metadata.Namespace,
Name: p.Metadata.Name,
@@ -702,14 +702,14 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
// Sync deployments
if deps, err := client.ListDeployments(); err == nil {
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.K8sDeployment{})
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.KubernetesDeployment{})
for _, d := range deps.Items {
image := ""
if len(d.Spec.Template.Spec.Containers) > 0 {
image = d.Spec.Template.Spec.Containers[0].Image
}
labelsJSON, _ := json.Marshal(d.Metadata.Labels)
h.db.Create(&models.K8sDeployment{
h.db.Create(&models.KubernetesDeployment{
ClusterID: cluster.ID,
Namespace: d.Metadata.Namespace,
Name: d.Metadata.Name,
@@ -727,12 +727,12 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
// Sync services
if svcs, err := client.ListServices(); err == nil {
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.K8sService{})
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.KubernetesService{})
for _, s := range svcs.Items {
portsJSON, _ := json.Marshal(s.Spec.Ports)
selectorJSON, _ := json.Marshal(s.Spec.Selector)
labelsJSON, _ := json.Marshal(s.Metadata.Labels)
h.db.Create(&models.K8sService{
h.db.Create(&models.KubernetesService{
ClusterID: cluster.ID,
Namespace: s.Metadata.Namespace,
Name: s.Metadata.Name,
@@ -748,7 +748,7 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
// Sync ingresses
if ings, err := client.ListIngresses(); err == nil {
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.K8sIngress{})
h.db.Where("cluster_id = ?", cluster.ID).Delete(&models.KubernetesIngress{})
for _, ing := range ings.Items {
hosts := []string{}
for _, rule := range ing.Spec.Rules {
@@ -764,7 +764,7 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
}
tlsHostsJSON, _ := json.Marshal(tlsHosts)
labelsJSON, _ := json.Marshal(ing.Metadata.Labels)
h.db.Create(&models.K8sIngress{
h.db.Create(&models.KubernetesIngress{
ClusterID: cluster.ID,
Namespace: ing.Metadata.Namespace,
Name: ing.Metadata.Name,
@@ -800,7 +800,7 @@ func (h *K8sHandler) SyncCluster(c *gin.Context) {
// ============================================================================
// GetPodLogs 获取 Pod 日志(支持 stream=true 实时流)
func (h *K8sHandler) GetPodLogs(c *gin.Context) {
func (h *KubernetesHandler) GetPodLogs(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
podName := c.Param("podName")
@@ -857,7 +857,7 @@ func (h *K8sHandler) GetPodLogs(c *gin.Context) {
// ============================================================================
// ExecTerminal WebSocket 终端 — 前端 WS → 后端 → K8s SPDY exec
func (h *K8sHandler) ExecTerminal(c *gin.Context) {
func (h *KubernetesHandler) ExecTerminal(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
podName := c.Param("podName")
@@ -970,7 +970,7 @@ func (h *K8sHandler) ExecTerminal(c *gin.Context) {
// ============================================================================
// ExecInPod 在 Pod 中执行命令 (文件浏览 / 单次命令)
func (h *K8sHandler) ExecInPod(c *gin.Context) {
func (h *KubernetesHandler) ExecInPod(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
podName := c.Param("podName")
@@ -1008,7 +1008,7 @@ func (h *K8sHandler) ExecInPod(c *gin.Context) {
// ============================================================================
// ScaleDeployment 缩放 Deployment 副本数
func (h *K8sHandler) ScaleDeployment(c *gin.Context) {
func (h *KubernetesHandler) ScaleDeployment(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
name := c.Param("name")
@@ -1040,7 +1040,7 @@ func (h *K8sHandler) ScaleDeployment(c *gin.Context) {
}
// RestartDeployment 重启 Deployment (滚动重启)
func (h *K8sHandler) RestartDeployment(c *gin.Context) {
func (h *KubernetesHandler) RestartDeployment(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
name := c.Param("name")
@@ -1064,7 +1064,7 @@ func (h *K8sHandler) RestartDeployment(c *gin.Context) {
// ============================================================================
// ListHPAs 获取 HPA 列表
func (h *K8sHandler) ListHPAs(c *gin.Context) {
func (h *KubernetesHandler) ListHPAs(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
client, _, err := h.getK8sClient(clusterID)
@@ -1083,7 +1083,7 @@ func (h *K8sHandler) ListHPAs(c *gin.Context) {
}
// CreateHPA 创建 HPA
func (h *K8sHandler) CreateHPA(c *gin.Context) {
func (h *KubernetesHandler) CreateHPA(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
var req k8sclient.CreateHPARequest
@@ -1112,7 +1112,7 @@ func (h *K8sHandler) CreateHPA(c *gin.Context) {
}
// DeleteHPA 删除 HPA
func (h *K8sHandler) DeleteHPA(c *gin.Context) {
func (h *KubernetesHandler) DeleteHPA(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
name := c.Param("name")
@@ -1136,7 +1136,7 @@ func (h *K8sHandler) DeleteHPA(c *gin.Context) {
// ============================================================================
// ListCronJobs 获取 CronJob 列表
func (h *K8sHandler) ListCronJobs(c *gin.Context) {
func (h *KubernetesHandler) ListCronJobs(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
client, _, err := h.getK8sClient(clusterID)
@@ -1155,7 +1155,7 @@ func (h *K8sHandler) ListCronJobs(c *gin.Context) {
}
// CreateCronJob 创建 CronJob
func (h *K8sHandler) CreateCronJob(c *gin.Context) {
func (h *KubernetesHandler) CreateCronJob(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
var req k8sclient.CreateCronJobRequest
@@ -1180,7 +1180,7 @@ func (h *K8sHandler) CreateCronJob(c *gin.Context) {
}
// SuspendCronJob 暂停/恢复 CronJob
func (h *K8sHandler) SuspendCronJob(c *gin.Context) {
func (h *KubernetesHandler) SuspendCronJob(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
name := c.Param("name")
@@ -1209,7 +1209,7 @@ func (h *K8sHandler) SuspendCronJob(c *gin.Context) {
}
// DeleteCronJob 删除 CronJob
func (h *K8sHandler) DeleteCronJob(c *gin.Context) {
func (h *KubernetesHandler) DeleteCronJob(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
name := c.Param("name")
@@ -1229,7 +1229,7 @@ func (h *K8sHandler) DeleteCronJob(c *gin.Context) {
}
// TriggerCronJob 手动触发 CronJob
func (h *K8sHandler) TriggerCronJob(c *gin.Context) {
func (h *KubernetesHandler) TriggerCronJob(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
name := c.Param("name")
@@ -1253,7 +1253,7 @@ func (h *K8sHandler) TriggerCronJob(c *gin.Context) {
// ============================================================================
// UpdateDeploymentImage 更新 Deployment 容器镜像 (CI webhook)
func (h *K8sHandler) UpdateDeploymentImage(c *gin.Context) {
func (h *KubernetesHandler) UpdateDeploymentImage(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
namespace := c.Param("namespace")
name := c.Param("name")
@@ -1290,8 +1290,12 @@ func (h *K8sHandler) UpdateDeploymentImage(c *gin.Context) {
// ============================================================================
// ListNamespaces 获取命名空间列表
func (h *K8sHandler) ListNamespaces(c *gin.Context) {
func (h *KubernetesHandler) ListNamespaces(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
// Support clusterCode param from new routes
if clusterID == 0 {
clusterID = h.resolveClusterCode(c.Param("clusterCode"))
}
client, _, err := h.getK8sClient(clusterID)
if err != nil {
@@ -1308,6 +1312,355 @@ func (h *K8sHandler) ListNamespaces(c *gin.Context) {
c.JSON(http.StatusOK, models.Response{Code: 200, Data: namespaces})
}
// ============================================================================
// ConfigMap & Secret (Kuboard-style namespace resources)
// ============================================================================
// ListConfigMaps 获取命名空间下的 ConfigMap 列表
func (h *KubernetesHandler) ListConfigMaps(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 {
clusterID = h.resolveClusterCode(c.Param("clusterCode"))
}
namespace := c.Param("namespace")
client, _, err := h.getK8sClient(clusterID)
if err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: err.Error()})
return
}
cms, err := client.ListConfigMaps(namespace)
if err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "K8s API error: " + err.Error()})
return
}
c.JSON(http.StatusOK, models.Response{Code: 200, Data: cms.Items})
}
// ListSecrets 获取命名空间下的 Secret 列表(仅名称+类型,不含值)
func (h *KubernetesHandler) ListSecrets(c *gin.Context) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 {
clusterID = h.resolveClusterCode(c.Param("clusterCode"))
}
namespace := c.Param("namespace")
client, _, err := h.getK8sClient(clusterID)
if err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: err.Error()})
return
}
secrets, err := client.ListSecrets(namespace)
if err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "K8s API error: " + err.Error()})
return
}
c.JSON(http.StatusOK, models.Response{Code: 200, Data: secrets.Items})
}
// ============================================================================
// Helpers
// ============================================================================
// resolveClusterCode resolves a cluster code to its numeric ID
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)
}
// 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 {
clusterID = h.resolveClusterCode(c.Param("clusterCode"))
}
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) ListDeploymentsNS(c *gin.Context) {
h.listDeploymentsWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) ListPodsNS(c *gin.Context) {
h.listPodsWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) ListServicesNS(c *gin.Context) {
h.listServicesWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) ListIngressesNS(c *gin.Context) {
h.listIngressesWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) ListHPAsNS(c *gin.Context) {
h.listHPAsWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) CreateHPANS(c *gin.Context) {
h.createHPAWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) DeleteHPANS(c *gin.Context) {
h.deleteHPAWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) ListCronJobsNS(c *gin.Context) {
h.listCronJobsWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) CreateCronJobNS(c *gin.Context) {
h.createCronJobWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) SuspendCronJobNS(c *gin.Context) {
h.suspendCronJobWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) TriggerCronJobNS(c *gin.Context) {
h.triggerCronJobWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) DeleteCronJobNS(c *gin.Context) {
h.deleteCronJobWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) ScaleDeploymentNS(c *gin.Context) {
h.scaleDeploymentWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) RestartDeploymentNS(c *gin.Context) {
h.restartDeploymentWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) UpdateDeploymentImageNS(c *gin.Context) {
h.updateDeploymentImageWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) GetPodLogsNS(c *gin.Context) {
h.getPodLogsWithNS(c, c.Param("namespace"))
}
func (h *KubernetesHandler) ExecInPodNS(c *gin.Context) {
h.execInPodWithNS(c, c.Param("namespace"))
}
// Internal helpers that resolve clusterCode and inject namespace
func (h *KubernetesHandler) listDeploymentsWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
deps, err := client.ListDeployments()
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
type DepSummary struct {
Namespace, Name string; Replicas, AvailableReplicas, ReadyReplicas int; Image string
}
result := []DepSummary{}
for _, d := range deps.Items {
if d.Metadata.Namespace != ns { continue }
image := ""; if len(d.Spec.Template.Spec.Containers) > 0 { image = d.Spec.Template.Spec.Containers[0].Image }
result = append(result, DepSummary{d.Metadata.Namespace, d.Metadata.Name, d.Spec.Replicas, d.Status.AvailableReplicas, d.Status.ReadyReplicas, image})
}
c.JSON(200, models.Response{Code: 200, Data: result})
}
func (h *KubernetesHandler) listPodsWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
pods, err := client.ListPods()
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
type PodSummary struct { Namespace, Name, Status, NodeName, IP string; RestartCount int; Image string }
result := []PodSummary{}
for _, p := range pods.Items {
if p.Metadata.Namespace != ns { continue }
image := ""; if len(p.Spec.Containers) > 0 { image = p.Spec.Containers[0].Image }
restarts := 0; if len(p.Status.ContainerStatuses) > 0 { restarts = p.Status.ContainerStatuses[0].RestartCount }
result = append(result, PodSummary{p.Metadata.Namespace, p.Metadata.Name, p.Status.Phase, p.Spec.NodeName, p.Status.PodIP, restarts, image})
}
c.JSON(200, models.Response{Code: 200, Data: result})
}
func (h *KubernetesHandler) listServicesWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
svcs, err := client.ListServices()
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
type SvcSummary struct { Namespace, Name, Type, ClusterIP string; Ports int }
result := []SvcSummary{}
for _, s := range svcs.Items {
if s.Metadata.Namespace != ns { continue }
result = append(result, SvcSummary{s.Metadata.Namespace, s.Metadata.Name, s.Spec.Type, s.Spec.ClusterIP, len(s.Spec.Ports)})
}
c.JSON(200, models.Response{Code: 200, Data: result})
}
func (h *KubernetesHandler) listIngressesWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
ings, err := client.ListIngresses()
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
type IngSummary struct { Namespace, Name string; Hosts []string; TLS bool }
result := []IngSummary{}
for _, ing := range ings.Items {
if ing.Metadata.Namespace != ns { continue }
hosts := []string{}
for _, rule := range ing.Spec.Rules { if rule.Host != "" { hosts = append(hosts, rule.Host) } }
result = append(result, IngSummary{ing.Metadata.Namespace, ing.Metadata.Name, hosts, len(ing.Spec.TLS) > 0})
}
c.JSON(200, models.Response{Code: 200, Data: result})
}
func (h *KubernetesHandler) listHPAsWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
hpas, err := client.ListHPAs()
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
filtered := []k8sclient.HPAItem{}
for _, h := range hpas.Items { if h.Metadata.Namespace == ns { filtered = append(filtered, h) } }
c.JSON(200, models.Response{Code: 200, Data: filtered})
}
func (h *KubernetesHandler) createHPAWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
var req k8sclient.CreateHPARequest
if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, models.Response{Code: 400, Message: "参数错误"}); return }
if req.Namespace == "" { req.Namespace = ns }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
hpa, err := client.CreateHPA(req)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "创建失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Data: hpa})
}
func (h *KubernetesHandler) deleteHPAWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if err := client.DeleteHPA(ns, c.Param("name")); err != nil { c.JSON(500, models.Response{Code: 500, Message: "删除失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Message: "已删除"})
}
func (h *KubernetesHandler) listCronJobsWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
cjs, err := client.ListCronJobs()
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
filtered := []k8sclient.CronJobItem{}
for _, cj := range cjs.Items { if cj.Metadata.Namespace == ns { filtered = append(filtered, cj) } }
c.JSON(200, models.Response{Code: 200, Data: filtered})
}
func (h *KubernetesHandler) createCronJobWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
var req k8sclient.CreateCronJobRequest
if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, models.Response{Code: 400, Message: "参数错误"}); return }
if req.Namespace == "" { req.Namespace = ns }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
cj, err := client.CreateCronJob(req)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "创建失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Data: cj})
}
func (h *KubernetesHandler) suspendCronJobWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
var req struct { Suspend bool `json:"suspend"` }; c.ShouldBindJSON(&req)
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if err := client.SuspendCronJob(ns, c.Param("name"), req.Suspend); err != nil { c.JSON(500, models.Response{Code: 500, Message: "操作失败: " + err.Error()}); return }
action := "恢复"; if req.Suspend { action = "暂停" }
c.JSON(200, models.Response{Code: 200, Message: "CronJob 已" + action})
}
func (h *KubernetesHandler) triggerCronJobWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if err := client.TriggerCronJob(ns, c.Param("name")); err != nil { c.JSON(500, models.Response{Code: 500, Message: "触发失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Message: "手动触发成功"})
}
func (h *KubernetesHandler) deleteCronJobWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if err := client.DeleteCronJob(ns, c.Param("name")); err != nil { c.JSON(500, models.Response{Code: 500, Message: "删除失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Message: "已删除"})
}
func (h *KubernetesHandler) scaleDeploymentWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
var req struct { Replicas int `json:"replicas"` }
if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, models.Response{Code: 400, Message: "参数错误"}); return }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if err := client.ScaleDeployment(ns, c.Param("name"), req.Replicas); err != nil { c.JSON(500, models.Response{Code: 500, Message: "扩缩容失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Message: fmt.Sprintf("已设置为 %d 副本", req.Replicas)})
}
func (h *KubernetesHandler) restartDeploymentWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if err := client.RestartDeployment(ns, c.Param("name")); err != nil { c.JSON(500, models.Response{Code: 500, Message: "重启失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Message: "重启指令已下发"})
}
func (h *KubernetesHandler) updateDeploymentImageWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
var req struct { Image string `json:"image"`; ContainerName string `json:"container_name"` }
if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, models.Response{Code: 400, Message: "参数错误"}); return }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if err := client.UpdateDeploymentImage(ns, c.Param("name"), req.ContainerName, req.Image); err != nil { c.JSON(500, models.Response{Code: 500, Message: "更新镜像失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Message: fmt.Sprintf("镜像已更新为 %s", req.Image)})
}
func (h *KubernetesHandler) getPodLogsWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
podName := c.Param("podName")
container := c.Query("container")
tailLines, _ := strconv.Atoi(c.DefaultQuery("tail", "200"))
stream := c.Query("stream") == "true"
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
if stream {
body, err := client.GetPodLogsStream(ns, podName, container, tailLines)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "获取日志流失败: " + err.Error()}); return }
defer body.Close()
c.Header("Content-Type", "text/plain; charset=utf-8")
c.Header("Cache-Control", "no-cache")
c.Stream(func(w io.Writer) bool {
buf := make([]byte, 4096); n, err := body.Read(buf)
if n > 0 { w.Write(buf[:n]); return true }
return err == nil
})
return
}
logs, err := client.GetPodLogs(ns, podName, container, tailLines)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "获取日志失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Data: gin.H{"logs": logs, "pod": podName, "namespace": ns}})
}
func (h *KubernetesHandler) execInPodWithNS(c *gin.Context, ns string) {
clusterID, _ := strconv.Atoi(c.Param("id"))
if clusterID == 0 { clusterID = h.resolveClusterCode(c.Param("clusterCode")) }
podName := c.Param("podName")
var req struct { Command []string `json:"command"`; Container string `json:"container"` }
if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, models.Response{Code: 400, Message: "参数错误"}); return }
client, _, err := h.getK8sClient(clusterID)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: err.Error()}); return }
result, err := client.ExecInPod(ns, podName, req.Container, req.Command)
if err != nil { c.JSON(500, models.Response{Code: 500, Message: "执行失败: " + err.Error()}); return }
c.JSON(200, models.Response{Code: 200, Data: result})
}
// ============================================================================
// Helpers
// ============================================================================
@@ -1342,8 +1695,8 @@ func parseMemResource(val string) int64 {
// getK8sClient builds a K8s API client from cluster's stored kubeconfig
func (h *K8sHandler) getK8sClient(clusterID int) (*k8sclient.Client, *models.K8sCluster, error) {
var cluster models.K8sCluster
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")
}
+50 -3
View File
@@ -65,8 +65,8 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
r.GET("/ws/metrics", middleware.JWTAuth(&cfg.JWT), metricsWSHandler.ServeWS)
// WebSocket K8s exec 交互终端 // Logan.Li
k8sHandler := handlers.NewK8sHandler(db)
r.GET("/ws/k8s-exec/:id/namespaces/:namespace/pods/:podName", middleware.JWTAuth(&cfg.JWT), k8sHandler.ExecTerminal)
k8sHandler := handlers.NewKubernetesHandler(db)
r.GET("/ws/kubernetes-exec/:id/namespaces/:namespace/pods/:podName", middleware.JWTAuth(&cfg.JWT), k8sHandler.ExecTerminal)
// 公开路由
authHandler := handlers.NewUserHandler(db, cfg)
@@ -235,7 +235,7 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
}
// K8s集群路由
clusters := authorized.Group("/k8s-clusters")
clusters := authorized.Group("/kubernetes-clusters")
{
clusters.GET("", k8sHandler.ListClusters)
clusters.GET("/:id", k8sHandler.GetCluster)
@@ -275,6 +275,53 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
clusters.GET("/:id/namespaces", k8sHandler.ListNamespaces)
}
// ============================================================================
// Kuboard-style namespace-scoped routes (/kubernetes/{clusterCode}/namespace/{ns}/...)
// ============================================================================
kubernetesRouter := authorized.Group("/kubernetes")
{
// Namespace overview
kubernetesRouter.GET("/:clusterCode/namespace/:namespace", func(c *gin.Context) {
k8sHandler.ListDeploymentsNS(c)
})
// Deployments
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/deployments", k8sHandler.ListDeploymentsNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/scale", k8sHandler.ScaleDeploymentNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/restart", k8sHandler.RestartDeploymentNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/deployments/:name/update-image", k8sHandler.UpdateDeploymentImageNS)
// Pods
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/pods", k8sHandler.ListPodsNS)
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/pods/:podName/logs", k8sHandler.GetPodLogsNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/pods/:podName/exec", k8sHandler.ExecInPodNS)
// Services
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/services", k8sHandler.ListServicesNS)
// Ingresses
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/ingresses", k8sHandler.ListIngressesNS)
// HPA
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/hpas", k8sHandler.ListHPAsNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/hpas", k8sHandler.CreateHPANS)
kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/hpas/:name", k8sHandler.DeleteHPANS)
// CronJob
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/cronjobs", k8sHandler.ListCronJobsNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/cronjobs", k8sHandler.CreateCronJobNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/cronjobs/:name/suspend", k8sHandler.SuspendCronJobNS)
kubernetesRouter.POST("/:clusterCode/namespace/:namespace/cronjobs/:name/trigger", k8sHandler.TriggerCronJobNS)
kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/cronjobs/:name", k8sHandler.DeleteCronJobNS)
// ConfigMap / Secret
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/configmaps", k8sHandler.ListConfigMaps)
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/secrets", k8sHandler.ListSecrets)
// Namespace list
kubernetesRouter.GET("/:clusterCode/namespaces", k8sHandler.ListNamespaces)
}
// 告警路由
alertHandler := handlers.NewAlertHandler(db)
alerts := authorized.Group("/alerts")