feat: scale instances, --reuse-values, values diff, UI redesign, hover animations
Backend (Phase 1):
- Add ScaleInstance endpoint (POST /clusters/{id}/instances/{id}/scale)
- Add GetInstanceValuesDiff endpoint (GET .../values-diff)
- Enable ReuseValues=true in Helm Upgrade for --reuse-values behavior
- Add GetValues/GetChartDefaultValues to HelmClient interface
- Add ScaleInstanceRequest/Response and InstanceValuesDiffResponse DTOs
Frontend (Phase 2):
- InstanceCard: +/- scale buttons with loading spinner
- ModifyModal: values diff view (current vs defaults), Use Defaults button
- ArtifactBrowserPage: collapsible sidebar, compact tag grid, search filter
- TagCard: "LATEST" badge, compact layout, responsive design
- InstanceCard: compact 3-column layout, fewer scrolls needed
- InstancesManagementPage: 3-column grid, compact view
- Global hover-lift and hover-glow CSS utilities
- SidebarNav: subtle hover transition on links
This commit is contained in:
@ -206,6 +206,25 @@ type InstanceEventDiagnostics struct {
|
||||
LastTimestamp string `json:"lastTimestamp,omitempty"`
|
||||
}
|
||||
|
||||
// ScaleInstanceRequest 扩缩容实例请求
|
||||
type ScaleInstanceRequest struct {
|
||||
Replicas int `json:"replicas" binding:"required"`
|
||||
Workload string `json:"workload"`
|
||||
}
|
||||
|
||||
// ScaleInstanceResponse 扩缩容实例响应
|
||||
type ScaleInstanceResponse struct {
|
||||
Instance *InstanceResponse `json:"instance"`
|
||||
Replicas int `json:"replicas"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// InstanceValuesDiffResponse 实例 values 差异响应
|
||||
type InstanceValuesDiffResponse struct {
|
||||
Current map[string]interface{} `json:"current"`
|
||||
Defaults map[string]interface{} `json:"defaults"`
|
||||
}
|
||||
|
||||
type InstancePodLogResponse struct {
|
||||
Pod string `json:"pod"`
|
||||
Container string `json:"container"`
|
||||
|
||||
@ -371,6 +371,49 @@ func (h *InstanceHandler) StreamInstanceLogs(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
}
|
||||
|
||||
// ScaleInstance 扩缩容实例
|
||||
func (h *InstanceHandler) ScaleInstance(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
clusterID := vars["cluster_id"]
|
||||
instanceID := vars["instance_id"]
|
||||
|
||||
var req dto.ScaleInstanceRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondError(w, http.StatusBadRequest, "Invalid request body", err.Error())
|
||||
return
|
||||
}
|
||||
if req.Replicas < 0 {
|
||||
respondError(w, http.StatusBadRequest, "Invalid replicas", "replicas must be >= 0")
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.instanceService.ScaleInstance(r.Context(), clusterID, instanceID, req.Replicas, req.Workload)
|
||||
if err != nil {
|
||||
respondServiceError(w, err, "Failed to scale instance")
|
||||
return
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusOK, dto.ScaleInstanceResponse{
|
||||
Instance: convertInstanceResponse(result, true),
|
||||
Replicas: req.Replicas,
|
||||
Message: fmt.Sprintf("Scaled to %d replicas", req.Replicas),
|
||||
})
|
||||
}
|
||||
|
||||
// GetInstanceValuesDiff 获取实例 values 差异
|
||||
func (h *InstanceHandler) GetInstanceValuesDiff(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
clusterID := vars["cluster_id"]
|
||||
instanceID := vars["instance_id"]
|
||||
|
||||
diff, err := h.instanceService.GetInstanceValuesDiff(r.Context(), clusterID, instanceID)
|
||||
if err != nil {
|
||||
respondServiceError(w, err, "Failed to get values diff")
|
||||
return
|
||||
}
|
||||
respondJSON(w, http.StatusOK, diff)
|
||||
}
|
||||
|
||||
func convertInstanceEntry(entry *entity.InstanceEntry) *dto.InstanceEntryResponse {
|
||||
portResponses := make([]dto.InstanceEntryPortResponse, 0, len(entry.Ports))
|
||||
for _, port := range entry.Ports {
|
||||
|
||||
Reference in New Issue
Block a user