- 前端: React 18 + TypeScript + Vite + Tailwind CSS + shadcn/ui - 后端: Go + Gin + GORM + JWT (golang-jwt/jwt/v5) - 功能: 服务器管理、K8s集群、监控告警、CI/CD、自动化运维、审批流程、审计日志 - 文档: 设计文档(ROADMAP/PDD/架构/模块)
346 lines
8.5 KiB
Go
346 lines
8.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"ezops/internal/models"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// K8sHandler K8s处理器
|
|
type K8sHandler struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewK8sHandler 创建K8s处理器
|
|
func NewK8sHandler(db *gorm.DB) *K8sHandler {
|
|
return &K8sHandler{db: db}
|
|
}
|
|
|
|
// ListClusters 获取集群列表
|
|
// @Summary 获取集群列表
|
|
// @Description 获取所有K8s集群列表
|
|
// @Tags K8s集群
|
|
// @Produce json
|
|
// @Security Bearer
|
|
// @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) {
|
|
var query models.PageQuery
|
|
c.ShouldBindQuery(&query)
|
|
|
|
var total int64
|
|
h.db.Model(&models.K8sCluster{}).Count(&total)
|
|
|
|
var clusters []models.K8sCluster
|
|
h.db.Offset(query.GetOffset()).Limit(query.GetLimit()).Find(&clusters)
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "success",
|
|
Data: models.ListResponse{
|
|
List: clusters,
|
|
Total: total,
|
|
},
|
|
})
|
|
}
|
|
|
|
// GetCluster 获取集群详情
|
|
// @Summary 获取集群详情
|
|
// @Description 获取指定K8s集群的详细信息
|
|
// @Tags K8s集群
|
|
// @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) {
|
|
id, _ := strconv.Atoi(c.Param("id"))
|
|
|
|
var cluster models.K8sCluster
|
|
if err := h.db.First(&cluster, id).Error; err != nil {
|
|
c.JSON(http.StatusNotFound, models.Response{
|
|
Code: 404,
|
|
Message: "集群不存在",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "success",
|
|
Data: cluster,
|
|
})
|
|
}
|
|
|
|
// CreateCluster 创建集群
|
|
// @Summary 创建集群
|
|
// @Description 创建新K8s集群
|
|
// @Tags K8s集群
|
|
// @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
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, models.Response{
|
|
Code: 400,
|
|
Message: "请求参数错误: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
cluster := models.K8sCluster{
|
|
Name: req.Name,
|
|
Code: req.Code,
|
|
Version: req.Version,
|
|
APIEndpoint: req.APIEndpoint,
|
|
KubeConfig: req.KubeConfig,
|
|
Description: req.Description,
|
|
Status: "healthy",
|
|
}
|
|
|
|
if err := h.db.Create(&cluster).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, models.Response{
|
|
Code: 500,
|
|
Message: "创建失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "创建成功",
|
|
Data: cluster,
|
|
})
|
|
}
|
|
|
|
// UpdateCluster 更新集群
|
|
// @Summary 更新集群
|
|
// @Description 更新指定K8s集群信息
|
|
// @Tags K8s集群
|
|
// @Accept json
|
|
// @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) {
|
|
id, _ := strconv.Atoi(c.Param("id"))
|
|
|
|
var req models.CreateK8sClusterRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, models.Response{
|
|
Code: 400,
|
|
Message: "请求参数错误: " + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
var cluster models.K8sCluster
|
|
if err := h.db.First(&cluster, id).Error; err != nil {
|
|
c.JSON(http.StatusNotFound, models.Response{
|
|
Code: 404,
|
|
Message: "集群不存在",
|
|
})
|
|
return
|
|
}
|
|
|
|
updates := map[string]interface{}{
|
|
"name": req.Name,
|
|
"version": req.Version,
|
|
"api_endpoint": req.APIEndpoint,
|
|
"kube_config": req.KubeConfig,
|
|
"description": req.Description,
|
|
}
|
|
|
|
if err := h.db.Model(&cluster).Updates(updates).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, models.Response{
|
|
Code: 500,
|
|
Message: "更新失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
h.db.First(&cluster, id)
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "更新成功",
|
|
Data: cluster,
|
|
})
|
|
}
|
|
|
|
// DeleteCluster 删除集群
|
|
// @Summary 删除集群
|
|
// @Description 删除指定K8s集群
|
|
// @Tags K8s集群
|
|
// @Produce json
|
|
// @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) {
|
|
id, _ := strconv.Atoi(c.Param("id"))
|
|
|
|
if err := h.db.Delete(&models.K8sCluster{}, id).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, models.Response{
|
|
Code: 500,
|
|
Message: "删除失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "删除成功",
|
|
})
|
|
}
|
|
|
|
// ListNodes 获取节点列表
|
|
// @Summary 获取节点列表
|
|
// @Description 获取指定集群的节点列表
|
|
// @Tags K8s集群
|
|
// @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) {
|
|
clusterID, _ := strconv.Atoi(c.Param("id"))
|
|
|
|
var nodes []models.K8sNode
|
|
h.db.Where("cluster_id = ?", clusterID).Find(&nodes)
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "success",
|
|
Data: nodes,
|
|
})
|
|
}
|
|
|
|
// ListPods 获取Pod列表
|
|
// @Summary 获取Pod列表
|
|
// @Description 获取指定集群的Pod列表
|
|
// @Tags K8s集群
|
|
// @Produce json
|
|
// @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) {
|
|
clusterID, _ := strconv.Atoi(c.Param("id"))
|
|
namespace := c.Query("namespace")
|
|
|
|
db := h.db.Where("cluster_id = ?", clusterID)
|
|
if namespace != "" {
|
|
db = db.Where("namespace = ?", namespace)
|
|
}
|
|
|
|
var pods []models.K8sPod
|
|
db.Find(&pods)
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "success",
|
|
Data: pods,
|
|
})
|
|
}
|
|
|
|
// ListDeployments 获取Deployment列表
|
|
// @Summary 获取Deployment列表
|
|
// @Description 获取指定集群的Deployment列表
|
|
// @Tags K8s集群
|
|
// @Produce json
|
|
// @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) {
|
|
clusterID, _ := strconv.Atoi(c.Param("id"))
|
|
namespace := c.Query("namespace")
|
|
|
|
db := h.db.Where("cluster_id = ?", clusterID)
|
|
if namespace != "" {
|
|
db = db.Where("namespace = ?", namespace)
|
|
}
|
|
|
|
var deployments []models.K8sDeployment
|
|
db.Find(&deployments)
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "success",
|
|
Data: deployments,
|
|
})
|
|
}
|
|
|
|
// ListServices 获取Service列表
|
|
// @Summary 获取Service列表
|
|
// @Description 获取指定集群的Service列表
|
|
// @Tags K8s集群
|
|
// @Produce json
|
|
// @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) {
|
|
clusterID, _ := strconv.Atoi(c.Param("id"))
|
|
namespace := c.Query("namespace")
|
|
|
|
db := h.db.Where("cluster_id = ?", clusterID)
|
|
if namespace != "" {
|
|
db = db.Where("namespace = ?", namespace)
|
|
}
|
|
|
|
var services []models.K8sService
|
|
db.Find(&services)
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "success",
|
|
Data: services,
|
|
})
|
|
}
|
|
|
|
// ListIngresses 获取Ingress列表
|
|
// @Summary 获取Ingress列表
|
|
// @Description 获取指定集群的Ingress列表
|
|
// @Tags K8s集群
|
|
// @Produce json
|
|
// @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) {
|
|
clusterID, _ := strconv.Atoi(c.Param("id"))
|
|
namespace := c.Query("namespace")
|
|
|
|
db := h.db.Where("cluster_id = ?", clusterID)
|
|
if namespace != "" {
|
|
db = db.Where("namespace = ?", namespace)
|
|
}
|
|
|
|
var ingresses []models.K8sIngress
|
|
db.Find(&ingresses)
|
|
|
|
c.JSON(http.StatusOK, models.Response{
|
|
Code: 200,
|
|
Message: "success",
|
|
Data: ingresses,
|
|
})
|
|
}
|