package api import ( "encoding/json" "net/http" "debtik/internal/sdwan" ) // ======================== SD-WAN Handlers ======================== func (s *Server) handleListSDWANGroups(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeJSON(w, http.StatusOK, []*sdwan.SDWANGroup{}) return } list := s.sdwanMgr.List() writeJSON(w, http.StatusOK, list) } func (s *Server) handleGetSDWANGroup(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeError(w, http.StatusServiceUnavailable, "sd-wan subsystem unavailable") return } id := r.PathValue("id") g, ok := s.sdwanMgr.Get(id) if !ok { writeError(w, http.StatusNotFound, "sd-wan group not found") return } writeJSON(w, http.StatusOK, g) } func (s *Server) handleSaveSDWANGroup(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeError(w, http.StatusServiceUnavailable, "sd-wan subsystem unavailable") return } var g sdwan.SDWANGroup if err := json.NewDecoder(r.Body).Decode(&g); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if err := s.sdwanMgr.Save(&g); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{ "success": true, "id": g.ID, "name": g.Name, "mode": g.Mode, }) } func (s *Server) handleDeleteSDWANGroup(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeError(w, http.StatusServiceUnavailable, "sd-wan subsystem unavailable") return } id := r.PathValue("id") if id == "" { writeError(w, http.StatusBadRequest, "group id required") return } if err := s.sdwanMgr.Delete(id); err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id}) } func (s *Server) handleSetSDWANGroupState(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeError(w, http.StatusServiceUnavailable, "sd-wan subsystem unavailable") return } id := r.PathValue("id") var req struct { Disabled bool `json:"disabled"` } _ = json.NewDecoder(r.Body).Decode(&req) if err := s.sdwanMgr.SetState(id, req.Disabled); err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled}) } func (s *Server) handleSaveSDWANMember(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeError(w, http.StatusServiceUnavailable, "sd-wan subsystem unavailable") return } id := r.PathValue("id") var mem sdwan.SDWANMember if err := json.NewDecoder(r.Body).Decode(&mem); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if mem.Interface == "" { if iface := r.PathValue("iface"); iface != "" { mem.Interface = iface } } if mem.Interface == "" && mem.ID == "" { writeError(w, http.StatusBadRequest, "interface is required") return } isUpdate := r.Method == http.MethodPut if !isUpdate { if g, ok := s.sdwanMgr.Get(id); ok && g != nil { for _, existing := range g.Members { if (mem.ID != "" && existing.ID == mem.ID) || (mem.Interface != "" && existing.Interface == mem.Interface) { isUpdate = true if mem.ID == "" { mem.ID = existing.ID } break } } } } var err error if isUpdate { err = s.sdwanMgr.UpdateMember(id, &mem) } else { err = s.sdwanMgr.AddMember(id, &mem) } if err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{ "success": true, "id": mem.ID, "interface": mem.Interface, "weight": mem.Weight, "priority": mem.Priority, "disabled": mem.Disabled, }) } func (s *Server) handleDeleteSDWANMember(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeError(w, http.StatusServiceUnavailable, "sd-wan subsystem unavailable") return } id := r.PathValue("id") iface := r.PathValue("iface") if id == "" || iface == "" { writeError(w, http.StatusBadRequest, "group id and member interface required") return } if err := s.sdwanMgr.DeleteMember(id, iface); err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "interface": iface}) } func (s *Server) handleGetSDWANTelemetry(w http.ResponseWriter, r *http.Request) { if s.sdwanMgr == nil { writeJSON(w, http.StatusOK, sdwan.TelemetrySummary{}) return } summary := s.sdwanMgr.GetSummary() writeJSON(w, http.StatusOK, summary) }