Files
llmgw/internal/cli/mirror_test.go
T
Ilker ManapandClaude Opus 5 16ec585411 Let the control plane ask the mirror for a model instead of pushing one at it
The mirror holds the weights, so the mirror does the downloading. A control
plane that had to pull the bytes itself and push them here would carry every
model twice over the network, through the one machine least able to spare the
bandwidth.

Two listeners, and the split is the point. Weights stay on plain HTTP where
every node can reach them: that path is eight nodes pulling forty gigabytes,
and putting a client certificate in front of it would mean re-certifying every
agent's fetcher in order to change how models are administered. Management gets
its own port, which can be given the fleet's CA — the same tlsconf the agent
stream uses, so this is a configuration rather than a new idea.

A fetch answers 202, not 200. The bytes are not here yet, and a caller that
read it as "done" would point a catalog at a file still arriving, which every
node would then copy. Progress is asked for rather than waited on, because no
client between here and the operator will hold a connection open for an hour.

A failed fetch is remembered with its reason. Forgetting it would leave the
control plane waiting on a model that is never coming, with nothing to say why.
Status falls back to reading the disk, so a restart does not report a model
that is plainly there as unknown.

Removal takes the whole version: a model split across files is useless with one
of them missing, and half a version on disk looks present and will not load. It
refuses while a download is running, because the fetch would carry on writing
and the file would reappear, looking like the delete had silently failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-27 09:34:48 +02:00

47 lines
1.5 KiB
Go

package cli
import (
"net/http"
"net/http/httptest"
"testing"
"gitea.mynodes.xyz/ilker/llmgw/internal/mirror"
)
func TestTheMirrorRefusesEverythingButReads(t *testing.T) {
// Stated here rather than inherited from http.FileServer, so a handler
// added later cannot quietly make the mirror writable — which would turn
// it into a way to replace a model with another one that every node then
// fetches without complaint.
h := readOnly(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
}))
for _, m := range []string{http.MethodGet, http.MethodHead} {
rec := httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequest(m, "/x.gguf", nil))
if rec.Code != http.StatusOK {
t.Errorf("%s was refused: %d", m, rec.Code)
}
}
for _, m := range []string{http.MethodPut, http.MethodPost, http.MethodDelete, http.MethodPatch} {
rec := httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequest(m, "/x.gguf", nil))
if rec.Code != http.StatusMethodNotAllowed {
t.Errorf("%s was allowed: %d", m, rec.Code)
}
}
}
func TestTheFilenameIsTakenFromTheURLWhenNotGiven(t *testing.T) {
for _, c := range []struct{ url, want string }{
{"https://h/a/b/model.gguf", "model.gguf"},
{"https://h/model.gguf?download=true", "model.gguf"},
{"model.gguf", "model.gguf"},
} {
if got := mirror.LastPathElement(c.url); got != c.want {
t.Errorf("mirror.LastPathElement(%q) = %q, want %q", c.url, got, c.want)
}
}
}