133 lines
3.7 KiB
Go
133 lines
3.7 KiB
Go
package v1
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"github.com/wild-cloud/wild-central/internal/services"
|
|
)
|
|
|
|
// ServicesListAll lists all registered services.
|
|
func (api *API) ServicesListAll(w http.ResponseWriter, r *http.Request) {
|
|
svcs, err := api.services.List()
|
|
if err != nil {
|
|
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list services: %v", err))
|
|
return
|
|
}
|
|
|
|
if svcs == nil {
|
|
svcs = []services.Service{}
|
|
}
|
|
|
|
respondJSON(w, http.StatusOK, map[string]any{
|
|
"services": svcs,
|
|
})
|
|
}
|
|
|
|
// ServicesGet retrieves a service by domain.
|
|
func (api *API) ServicesGet(w http.ResponseWriter, r *http.Request) {
|
|
domain := mux.Vars(r)["domain"]
|
|
|
|
svc, err := api.services.Get(domain)
|
|
if err != nil {
|
|
respondError(w, http.StatusNotFound, fmt.Sprintf("Service not found: %v", err))
|
|
return
|
|
}
|
|
|
|
respondJSON(w, http.StatusOK, svc)
|
|
}
|
|
|
|
// ServicesRegister creates or updates a service registration.
|
|
func (api *API) ServicesRegister(w http.ResponseWriter, r *http.Request) {
|
|
var svc services.Service
|
|
if err := json.NewDecoder(r.Body).Decode(&svc); err != nil {
|
|
respondError(w, http.StatusBadRequest, fmt.Sprintf("Invalid request body: %v", err))
|
|
return
|
|
}
|
|
|
|
// Validate routes
|
|
for i, r := range svc.Routes {
|
|
for _, p := range r.Paths {
|
|
if !strings.HasPrefix(p, "/") {
|
|
respondError(w, http.StatusBadRequest, fmt.Sprintf("Route %d: path prefix must start with /: %q", i, p))
|
|
return
|
|
}
|
|
}
|
|
for _, cidr := range r.IPAllow {
|
|
if _, _, err := net.ParseCIDR(cidr); err != nil {
|
|
respondError(w, http.StatusBadRequest, fmt.Sprintf("Route %d: invalid CIDR in ipAllow: %q", i, cidr))
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := api.services.Register(svc); err != nil {
|
|
respondError(w, http.StatusBadRequest, fmt.Sprintf("Failed to register service: %v", err))
|
|
return
|
|
}
|
|
|
|
// Return the stored version (has defaults applied)
|
|
stored, _ := api.services.Get(svc.Domain)
|
|
respondJSON(w, http.StatusCreated, map[string]any{
|
|
"message": fmt.Sprintf("Service %q registered", svc.Domain),
|
|
"service": stored,
|
|
})
|
|
}
|
|
|
|
// ServicesUpdate applies partial updates to a service.
|
|
func (api *API) ServicesUpdate(w http.ResponseWriter, r *http.Request) {
|
|
domain := mux.Vars(r)["domain"]
|
|
|
|
var updates map[string]any
|
|
if err := json.NewDecoder(r.Body).Decode(&updates); err != nil {
|
|
respondError(w, http.StatusBadRequest, fmt.Sprintf("Invalid request body: %v", err))
|
|
return
|
|
}
|
|
|
|
if err := api.services.Update(domain, updates); err != nil {
|
|
respondError(w, http.StatusNotFound, fmt.Sprintf("Failed to update service: %v", err))
|
|
return
|
|
}
|
|
|
|
svc, _ := api.services.Get(domain)
|
|
respondJSON(w, http.StatusOK, map[string]any{
|
|
"message": fmt.Sprintf("Service %q updated", domain),
|
|
"service": svc,
|
|
})
|
|
}
|
|
|
|
// ServicesDeregister removes a service registration.
|
|
func (api *API) ServicesDeregister(w http.ResponseWriter, r *http.Request) {
|
|
domain := mux.Vars(r)["domain"]
|
|
|
|
if err := api.services.Deregister(domain); err != nil {
|
|
respondError(w, http.StatusNotFound, fmt.Sprintf("Failed to deregister service: %v", err))
|
|
return
|
|
}
|
|
|
|
respondMessage(w, http.StatusOK, fmt.Sprintf("Service %q deregistered", domain))
|
|
}
|
|
|
|
// ServicesDeregisterBySource removes all services from a source with a given backend.
|
|
func (api *API) ServicesDeregisterBySource(w http.ResponseWriter, r *http.Request) {
|
|
source := r.URL.Query().Get("source")
|
|
backend := r.URL.Query().Get("backend")
|
|
|
|
if source == "" {
|
|
respondError(w, http.StatusBadRequest, "source query parameter is required")
|
|
return
|
|
}
|
|
|
|
if err := api.services.DeregisterBySource(source, backend); err != nil {
|
|
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to deregister: %v", err))
|
|
return
|
|
}
|
|
|
|
respondMessage(w, http.StatusOK, fmt.Sprintf("Services from %q deregistered", source))
|
|
}
|