ctl federation add/list/remove/sync keeps peers in the store (migration 0029); their /v1/models are offered here as external models named PEER/MODEL and kept in step, a model still named by a fallback kept withdrawn. Peers are checked at /ready, timed, and taken out of routing while down. Requests to a peer carry x-llmgw-hop and are refused (508) when they come back to a cluster they passed through; residency and no_store keep requests off peers; X-Request-Id and, with --send-tags, attribution tags go along. ctl model fallbacks sets overflow to a peer. Console view, metrics, admin API routes and docs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
38 lines
1.3 KiB
Go
38 lines
1.3 KiB
Go
package cli
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/control/adminapi"
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/control/federation"
|
|
)
|
|
|
|
func TestTheConsoleShowsEachPeerAndOpensItsModels(t *testing.T) {
|
|
m, _ := consoleWith(t, cFederation)
|
|
m.data.federation = adminapi.FederationView{Cluster: "c-west", Peers: []federation.Status{
|
|
{Name: "east", URL: "https://east.example", Cluster: "c-east",
|
|
Health: federation.Health{Up: true, Latency: 12 * time.Millisecond, Checked: time.Now()},
|
|
LatencyMs: 12, Models: []federation.ModelStatus{{Name: "east/qwen", Upstream: "qwen"},
|
|
{Name: "east/old", Upstream: "old", Withdrawn: true}}},
|
|
{Name: "north", URL: "https://north.example", Health: federation.Health{Error: "the peer did not answer"}},
|
|
}}
|
|
var tm tea.Model = m
|
|
view := tm.View()
|
|
for _, want := range []string{"east", "12.0ms", "north", "down", "c-west"} {
|
|
if !strings.Contains(view, want) {
|
|
t.Errorf("the federation view has no %q:\n%s", want, view)
|
|
}
|
|
}
|
|
tm = press(tm, "enter")
|
|
view = tm.View()
|
|
for _, want := range []string{"east/qwen", "east/old", "withdrawn", "c-east"} {
|
|
if !strings.Contains(view, want) {
|
|
t.Errorf("the peer's dialog has no %q:\n%s", want, view)
|
|
}
|
|
}
|
|
}
|