feat(panel): fleet

This commit is contained in:
Lemon-miaow committed 2026-07-01 03:46:07 +08:00
1 parent 742f15f348
commit d2de11af22
14 files changed
+978 -38

No files matched your search

+64 -5
View File
@@ -31,6 +31,11 @@ type fakeRepo struct {
// the account_links-bridged web view of the same data.
allowUUID map[string]map[string]bool
mine map[string][]MyServerView
// owners mirrors the ServerOwners join (name -> owner display identity); only
// claimed servers appear. ownersErr forces the lookup to fail so a test can
// prove the fleet read degrades to owner-less rows rather than 500ing.
owners map[string]string
ownersErr error
claimOK map[string]bool // name -> claim succeeds; absent name -> ErrNotFound
audits []AuditEntry
joins []string
@@ -139,6 +144,7 @@ func newFakeRepo() *fakeRepo {
linked: map[string]bool{}, quota: map[string]bool{},
allowlist: map[string]map[string]bool{}, allowUUID: map[string]map[string]bool{},
mine: map[string][]MyServerView{},
owners: map[string]string{},
claimOK: map[string]bool{},
seeded: map[string]bool{}, aliases: map[string]string{},
linkCodes: map[string]fakeLinkCode{}, links: map[string]string{},
@@ -411,6 +417,12 @@ func (f *fakeRepo) RecordJoin(_ context.Context, n, uuid string) error {
func (f *fakeRepo) MyServers(_ context.Context, u string) ([]MyServerView, error) {
return f.mine[u], nil
}
func (f *fakeRepo) ServerOwners(_ context.Context) (map[string]string, error) {
if f.ownersErr != nil {
return nil, f.ownersErr
}
return f.owners, nil
}
func (f *fakeRepo) SeedServer(_ context.Context, name, subdomain string) error {
if f.seedErr != nil {
return f.seedErr
@@ -861,21 +873,68 @@ func TestFleetAdminRead(t *testing.T) {
}
})
t.Run("admin reads the whole fleet", func(t *testing.T) {
api := newTestAPI(newFakeRepo(), cl)
// fleetRow mirrors the on-the-wire fleetServerView: the lifecycle fields plus
// the presentational owner join. A server absent from ServerOwners (unclaimed)
// or a failed lookup must serialize owner as "" (omitempty drops it).
type fleetRow struct {
Name string `json:"name"`
Owner string `json:"owner"`
}
adminAPI := func(repo *fakeRepo) *API {
api := newTestAPI(repo, cl)
api.External = staticExternal{p: &Principal{UserID: "a1", Email: "[email protected]",
Role: "admin", ViaAdminAccess: true}}
return api
}
readFleet := func(t *testing.T, api *API) []fleetRow {
t.Helper()
w := do(api.ExternalHandler(), "GET", "/api/v1/fleet", "", nil)
if w.Code != http.StatusOK {
t.Fatalf("code = %d, want 200 (%s)", w.Code, w.Body.String())
}
var got map[string][]ServerInfo
var got map[string][]fleetRow
if err := json.Unmarshal(w.Body.Bytes(), &got); err != nil {
t.Fatalf("body not JSON: %v", err)
}
return got["servers"]
}
t.Run("admin reads the whole fleet", func(t *testing.T) {
rows := readFleet(t, adminAPI(newFakeRepo()))
// Fleet-wide: all three servers, not a caller-scoped subset.
if len(got["servers"]) != 3 {
t.Fatalf("servers = %d, want 3 (the fleet read must not be caller-scoped)", len(got["servers"]))
if len(rows) != 3 {
t.Fatalf("servers = %d, want 3 (the fleet read must not be caller-scoped)", len(rows))
}
})
t.Run("owner merges for claimed, absent for unclaimed", func(t *testing.T) {
repo := newFakeRepo()
// Only "survival" is claimed; "creative"/"skyblock" stay unowned.
repo.owners["survival"] = "[email protected]"
byName := map[string]string{}
for _, r := range readFleet(t, adminAPI(repo)) {
byName[r.Name] = r.Owner
}
if byName["survival"] != "[email protected]" {
t.Fatalf("survival owner = %q, want [email protected]", byName["survival"])
}
if byName["creative"] != "" {
t.Fatalf("creative owner = %q, want empty (unclaimed)", byName["creative"])
}
})
t.Run("owner lookup failure degrades to owner-less rows", func(t *testing.T) {
repo := newFakeRepo()
repo.owners["survival"] = "[email protected]" // would merge, but the lookup errors
repo.ownersErr = fmt.Errorf("postgres unreachable")
rows := readFleet(t, adminAPI(repo)) // must still be 200, not 500
if len(rows) != 3 {
t.Fatalf("servers = %d, want 3 (a Postgres blip must not drop the fleet)", len(rows))
}
for _, r := range rows {
if r.Owner != "" {
t.Fatalf("%s owner = %q, want empty (owner lookup failed → degrade)", r.Name, r.Owner)
}
}
})
}