- Revoking a server's tools takes them from every level beneath too, and a level left naming no tool stays closed ([]) while any level above or beneath names tools: an organization's revoke left its teams the copies their first grants took, and going back to no list opened the level to what was above it. A closed level is shown on the page and in the console with an action to open it (store.OpenTools). A key's owner's list is among the levels above a key. - The flag check matches short flags as written again (-m, -hf, -mu were let through), takes a long flag's beginning for it only for the engines that parse with argparse (vLLM, SGLang, ComfyUI: --li is --listen), so llama.cpp's own --chat-template is not refused, and refuses llama.cpp's short spellings (-hfr, -hff, -mm, -jf, …). - A stored model with an adapter by Hugging Face id can be changed again: what it already had is not asked about anew. - The catalog reads a Hugging Face id as the agent does (engines.IsHubID). - The page's form cannot move llmgw:admin to another address. - server init skips the memory check only where the gateway already runs, not wherever a half-finished first run left server.yaml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
53 lines
2.0 KiB
Go
53 lines
2.0 KiB
Go
package cli
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/preflight"
|
|
)
|
|
|
|
func TestTheMemoryAMachineNeedsCountsWhatItServes(t *testing.T) {
|
|
in := &serverInit{}
|
|
mb, what := in.servingMemoryMB(false)
|
|
need := preflight.Needs[preflight.RoleControl].MemoryMB + mb
|
|
if what == "" || need <= 7941 || need > 11961 {
|
|
t.Errorf("node, starter and judges here: need %d MB (%q); an 8 GB machine must fail and a 12 GB one pass", need, what)
|
|
}
|
|
// Judges on machines of their own take their share off this one.
|
|
if mb2, _ := in.servingMemoryMB(true); mb2 >= mb {
|
|
t.Errorf("with judge machines %d MB, without %d", mb2, mb)
|
|
}
|
|
// A control plane that serves nothing needs only its own.
|
|
if mb, what := (&serverInit{noNode: true}).servingMemoryMB(false); mb != 0 || what != "" {
|
|
t.Errorf("no node: %d %q", mb, what)
|
|
}
|
|
if mb, _ := (&serverInit{noModel: true, noGuardModel: true}).servingMemoryMB(false); mb != 0 {
|
|
t.Errorf("nothing served: %d", mb)
|
|
}
|
|
// Without a mirror no judge is fetched, so none is counted.
|
|
if mb, what := (&serverInit{noMirror: true}).servingMemoryMB(false); mb != 0 {
|
|
t.Errorf("no mirror, nothing to fetch: %d %q", mb, what)
|
|
}
|
|
}
|
|
|
|
func TestSetupRunAgainOnAMachineAlreadySetUpIsNotRefusedItsMemory(t *testing.T) {
|
|
// The docs fix a certificate with server init --host on a machine set up
|
|
// before the check: it installs nothing it does not already serve.
|
|
dir := t.TempDir()
|
|
cfg := dir + "/server.yaml"
|
|
if err := os.WriteFile(cfg, []byte("listen: :8080\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
in := &serverInit{unitPath: dir + "/llmgw-server.service", etcDir: dir, serviceActive: func() bool { return true }}
|
|
if err := in.checkMemory(); err != nil {
|
|
t.Errorf("refused: %v", err)
|
|
}
|
|
// A first run that stopped half way left server.yaml and serves nothing:
|
|
// it still would install the models, and is checked.
|
|
in.serviceActive = func() bool { return false }
|
|
if in.alreadyServing() {
|
|
t.Error("a machine whose gateway is not running was taken for one serving")
|
|
}
|
|
}
|