Files
llmgw/internal/control/adminapi/presets.go
T
2026-10-13 16:14:55 +02:00

115 lines
3.6 KiB
Go

package adminapi
import (
"context"
"encoding/json"
"errors"
"net/http"
"time"
"gitea.mynodes.xyz/ilker/llmgw/internal/control/catalog"
)
// PresetsView is the models that come with llmgw, and whether the leader adds
// them by itself.
type PresetsView struct {
// Auto is whether a preset is added when a node fits it and the catalog
// has no model that makes what it makes (presets.auto).
Auto bool `json:"auto"`
Presets []PresetView `json:"presets"`
}
// PresetView is one preset as it stands in this cluster.
type PresetView struct {
Name string `json:"name"`
Makes string `json:"makes"`
Description string `json:"description"`
Card string `json:"card"`
Licence catalog.License `json:"licence"`
// Fits is whether some node has a card that meets the preset's need;
// FitsClasses names those classes.
Fits bool `json:"fits"`
FitsClasses []string `json:"fits_classes,omitempty"`
InCatalog bool `json:"in_catalog"`
// AddedBy is "auto" when the leader added it, who did otherwise, ""
// when it was not added as a preset; AddedAt is when.
AddedBy string `json:"added_by,omitempty"`
AddedAt time.Time `json:"added_at,omitzero"`
// Declined is whether somebody removed it after it was added, so it is
// not added again by itself; adding it again clears that.
Declined bool `json:"declined"`
}
// PresetsAutoRequest turns the automatic adding of presets on or off.
type PresetsAutoRequest struct {
On bool `json:"on"`
}
// errPresetsUnavailable is a control plane without the store presets are
// kept in.
var errPresetsUnavailable = errors.New("this control plane has no store, so presets cannot be added here")
// Presets is the presets as they stand in this cluster.
func (a *API) Presets(ctx context.Context) (PresetsView, error) {
return PresetsView{}, errPresetsUnavailable
}
// AddPreset adds the preset of that name, and clears its decline.
func (a *API) AddPreset(ctx context.Context, name, by string) error {
return errPresetsUnavailable
}
// SetAutoPresets turns presets.auto on or off.
func (a *API) SetAutoPresets(ctx context.Context, on bool, by string) error {
return errPresetsUnavailable
}
func (a *API) registerPresets(mux Mux) {
mux.HandleFunc("GET /api/v1/presets", func(w http.ResponseWriter, r *http.Request) {
v, err := a.Presets(r.Context())
if err != nil {
writeError(w, presetStatus(err), err.Error())
return
}
writeJSON(w, http.StatusOK, v)
})
mux.HandleFunc("POST /api/v1/presets/{name}", func(w http.ResponseWriter, r *http.Request) {
if err := a.AddPreset(r.Context(), r.PathValue("name"), actorOf(r)); err != nil {
writeError(w, presetStatus(err), err.Error())
return
}
writeJSON(w, http.StatusOK, ModelAdded{Added: r.PathValue("name")})
})
mux.HandleFunc("PUT /api/v1/presets/auto", func(w http.ResponseWriter, r *http.Request) {
var req PresetsAutoRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
if err := a.SetAutoPresets(r.Context(), req.On, actorOf(r)); err != nil {
writeError(w, presetStatus(err), err.Error())
return
}
v, err := a.Presets(r.Context())
if err != nil {
writeError(w, presetStatus(err), err.Error())
return
}
writeJSON(w, http.StatusOK, v)
})
}
// errNoSuchPreset is a name no preset has.
var errNoSuchPreset = errors.New("no preset of that name")
func presetStatus(err error) int {
switch {
case errors.Is(err, errPresetsUnavailable):
return http.StatusNotImplemented
case errors.Is(err, errNoSuchPreset):
return http.StatusNotFound
default:
return http.StatusBadRequest
}
}