package rest import ( "encoding/json" "net/http" "github.com/gorilla/mux" "github.com/ocdp/cluster-service/internal/adapter/input/http/dto" "github.com/ocdp/cluster-service/internal/domain/entity" "github.com/ocdp/cluster-service/internal/domain/service" ) // ValuesTemplateHandler Values Template Handler type ValuesTemplateHandler struct { valuesTemplateService *service.ValuesTemplateService } // NewValuesTemplateHandler 创建 Values Template Handler func NewValuesTemplateHandler(valuesTemplateService *service.ValuesTemplateService) *ValuesTemplateHandler { return &ValuesTemplateHandler{ valuesTemplateService: valuesTemplateService, } } // CreateValuesTemplate 创建 Values 模板 // @Summary 创建 Values 模板 // @Description 新增 Values 模板配置(带版本管理) // @Tags Values Templates // @Accept json // @Produce json // @Security BearerAuth // @Param request body dto.CreateValuesTemplateRequest true "Values 模板信息" // @Success 201 {object} dto.ValuesTemplateResponse // @Failure 400 {object} dto.ErrorResponse // @Router /values-templates [post] func (h *ValuesTemplateHandler) CreateValuesTemplate(w http.ResponseWriter, r *http.Request) { var req dto.CreateValuesTemplateRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { respondError(w, http.StatusBadRequest, "Invalid request body", err.Error()) return } // 获取用户信息 workspaceID := r.Header.Get("X-Workspace-ID") ownerID := r.Header.Get("X-User-ID") template, err := h.valuesTemplateService.Create( r.Context(), workspaceID, ownerID, req.ChartReferenceID, req.Name, req.Description, req.ValuesYAML, req.IsDefault, ) if err != nil { respondError(w, http.StatusBadRequest, "Failed to create values template", err.Error()) return } response := toValuesTemplateResponse(template) respondJSON(w, http.StatusCreated, response) } // GetValuesTemplate 获取 Values 模板详情 // @Summary 获取 Values 模板 // @Tags Values Templates // @Produce json // @Security BearerAuth // @Param template_id path string true "Template ID" // @Success 200 {object} dto.ValuesTemplateResponse // @Failure 404 {object} dto.ErrorResponse // @Router /values-templates/{template_id} [get] func (h *ValuesTemplateHandler) GetValuesTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) templateID := vars["template_id"] template, err := h.valuesTemplateService.GetByID(r.Context(), templateID) if err != nil { respondError(w, http.StatusNotFound, "Values template not found", err.Error()) return } response := toValuesTemplateResponse(template) respondJSON(w, http.StatusOK, response) } // GetAllValuesTemplates 获取所有 Values 模板 // @Summary 列出所有 Values 模板 // @Tags Values Templates // @Produce json // @Security BearerAuth // @Success 200 {array} dto.ValuesTemplateResponse // @Failure 500 {object} dto.ErrorResponse // @Router /values-templates [get] func (h *ValuesTemplateHandler) GetAllValuesTemplates(w http.ResponseWriter, r *http.Request) { workspaceID := r.Header.Get("X-Workspace-ID") role := r.Header.Get("X-User-Role") var templates []*dto.ValuesTemplateResponse // Admin 可以看到所有,其他用户只看自己 workspace if role == "admin" { allTemplates, err := h.valuesTemplateService.List(r.Context()) if err != nil { respondError(w, http.StatusInternalServerError, "Failed to list values templates", err.Error()) return } for _, t := range allTemplates { templates = append(templates, toValuesTemplateResponse(t)) } } else if workspaceID != "" { workspaceTemplates, err := h.valuesTemplateService.GetByWorkspace(r.Context(), workspaceID) if err != nil { respondError(w, http.StatusInternalServerError, "Failed to list values templates", err.Error()) return } for _, t := range workspaceTemplates { templates = append(templates, toValuesTemplateResponse(t)) } } respondJSON(w, http.StatusOK, templates) } // GetValuesTemplatesByChartReference 获取 Chart Reference 的所有 Values 模板 // @Summary 获取 Chart Reference 的 Values 模板 // @Tags Values Templates // @Produce json // @Security BearerAuth // @Param chart_reference_id path string true "Chart Reference ID" // @Success 200 {array} dto.ValuesTemplateResponse // @Failure 500 {object} dto.ErrorResponse // @Router /chart-references/{chart_reference_id}/values-templates [get] func (h *ValuesTemplateHandler) GetValuesTemplatesByChartReference(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) chartRefID := vars["chart_reference_id"] templates, err := h.valuesTemplateService.GetByChartReference(r.Context(), chartRefID) if err != nil { respondError(w, http.StatusInternalServerError, "Failed to list values templates", err.Error()) return } responses := make([]*dto.ValuesTemplateResponse, 0, len(templates)) for _, t := range templates { responses = append(responses, toValuesTemplateResponse(t)) } respondJSON(w, http.StatusOK, responses) } // GetValuesTemplateHistory 获取模板的版本历史 // @Summary 获取 Values 模板版本历史 // @Tags Values Templates // @Produce json // @Security BearerAuth // @Param chart_reference_id path string true "Chart Reference ID" // @Param name query string true "Template Name" // @Success 200 {array} dto.ValuesTemplateResponse // @Failure 500 {object} dto.ErrorResponse // @Router /chart-references/{chart_reference_id}/values-templates/history [get] func (h *ValuesTemplateHandler) GetValuesTemplateHistory(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) chartRefID := vars["chart_reference_id"] name := r.URL.Query().Get("name") if name == "" { respondError(w, http.StatusBadRequest, "Template name is required", "") return } templates, err := h.valuesTemplateService.GetHistory(r.Context(), chartRefID, name) if err != nil { respondError(w, http.StatusInternalServerError, "Failed to get values template history", err.Error()) return } responses := make([]*dto.ValuesTemplateResponse, 0, len(templates)) for _, t := range templates { responses = append(responses, toValuesTemplateResponse(t)) } respondJSON(w, http.StatusOK, responses) } // UpdateValuesTemplate 更新 Values 模板 // @Summary 更新 Values 模板 // @Tags Values Templates // @Accept json // @Produce json // @Security BearerAuth // @Param template_id path string true "Template ID" // @Param request body dto.UpdateValuesTemplateRequest true "更新内容" // @Success 200 {object} dto.ValuesTemplateResponse // @Failure 404 {object} dto.ErrorResponse // @Router /values-templates/{template_id} [put] func (h *ValuesTemplateHandler) UpdateValuesTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) templateID := vars["template_id"] var req dto.UpdateValuesTemplateRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { respondError(w, http.StatusBadRequest, "Invalid request body", err.Error()) return } isDefault := false if req.IsDefault != nil { isDefault = *req.IsDefault } template, err := h.valuesTemplateService.Update( r.Context(), templateID, req.Description, req.ValuesYAML, isDefault, ) if err != nil { respondError(w, http.StatusBadRequest, "Failed to update values template", err.Error()) return } response := toValuesTemplateResponse(template) respondJSON(w, http.StatusOK, response) } // DeleteValuesTemplate 删除 Values 模板 // @Summary 删除 Values 模板 // @Tags Values Templates // @Produce json // @Security BearerAuth // @Param template_id path string true "Template ID" // @Success 204 {string} string "No Content" // @Failure 404 {object} dto.ErrorResponse // @Router /values-templates/{template_id} [delete] func (h *ValuesTemplateHandler) DeleteValuesTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) templateID := vars["template_id"] if err := h.valuesTemplateService.Delete(r.Context(), templateID); err != nil { respondError(w, http.StatusNotFound, "Failed to delete values template", err.Error()) return } w.WriteHeader(http.StatusNoContent) } // RollbackValuesTemplate 回滚到指定版本 // @Summary 回滚 Values 模板 // @Tags Values Templates // @Accept json // @Produce json // @Security BearerAuth // @Param chart_reference_id path string true "Chart Reference ID" // @Param request body dto.RollbackValuesTemplateRequest true "回滚信息" // @Success 200 {object} dto.ValuesTemplateResponse // @Failure 404 {object} dto.ErrorResponse // @Router /chart-references/{chart_reference_id}/values-templates/rollback [post] func (h *ValuesTemplateHandler) RollbackValuesTemplate(w http.ResponseWriter, r *http.Request) { var req dto.RollbackValuesTemplateRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { respondError(w, http.StatusBadRequest, "Invalid request body", err.Error()) return } template, err := h.valuesTemplateService.Rollback(r.Context(), req.TemplateID) if err != nil { respondError(w, http.StatusBadRequest, "Failed to rollback values template", err.Error()) return } response := toValuesTemplateResponse(template) respondJSON(w, http.StatusOK, response) } // toValuesTemplateResponse 转换为响应 DTO func toValuesTemplateResponse(template *entity.ValuesTemplate) *dto.ValuesTemplateResponse { return &dto.ValuesTemplateResponse{ ID: template.ID, WorkspaceID: template.WorkspaceID, OwnerID: template.OwnerID, ChartReferenceID: template.ChartReferenceID, Name: template.Name, Description: template.Description, ValuesYAML: template.ValuesYAML, Version: template.Version, IsDefault: template.IsDefault, CreatedAt: template.CreatedAt.Format("2006-01-02T15:04:05Z07:00"), UpdatedAt: template.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"), } }