feat(api): 集群列表读改走 informer 缓存,审核队列、我的提交与备份列表改为服务端分页筛选并一次批量查构建,面板三页跟进

This commit is contained in:
Lemon-miaow committed 2026-09-25 18:13:21 +08:00
1 parent 0a66385d9f
commit 1054e62fa9
41 files changed
+1642 -295

No files matched your search

+6 -3
View File
@@ -87,8 +87,11 @@ func ControlPlaneRBAC(p Params) RBAC {
// follow). It also Gets the world PVC before backup/restore
// (internal/api.k8scluster.WorldVolumeExists) so a never-started or reaped
// world is refused up front instead of leaving a Job Pending on a missing
// claim. felis-api uses a DIRECT client, so it needs no list/watch beyond the
// explicit List calls — and the PVC grant is get-only, mirroring that.
// claim. felis-api reads the fleet (velocity's pull, the fleet page, the wake
// cap) from an informer cache of minecraftservers, hence watch on that one
// resource; everything else goes through a DIRECT client, so it needs no
// list/watch beyond the explicit List calls — and the PVC grant is get-only,
// mirroring that.
//
// The read-side grant is deliberately minimal: pods:list + pods/log:get, NOT
// pods:get — the streamer lists pods by the server label then reads the chosen
@@ -98,7 +101,7 @@ func ControlPlaneRBAC(p Params) RBAC {
func APIMinecraftRole(p Params) *rbacv1.Role {
p = p.withDefaults()
return role(p.MinecraftNamespace, "felis-api", ComponentAPI, []rbacv1.PolicyRule{
rule([]string{groupFelis}, []string{"minecraftservers"}, []string{"get", "list", "create", "patch"}),
rule([]string{groupFelis}, []string{"minecraftservers"}, []string{"get", "list", "watch", "create", "patch"}),
rule([]string{groupCore}, []string{"secrets"}, []string{"get"}),
// get-only: WorldVolumeExists does a single direct Get of the world PVC;
// nothing in felis-api lists or deletes PVCs.
+7 -1
View File
@@ -107,7 +107,8 @@ func TestAPIRole_CreatesJobsInBothNamespaces(t *testing.T) {
// what it must NOT have: no status writes, no delete.
func TestAPIRole_MinecraftPowersExact(t *testing.T) {
mc := roleByName(t, ControlPlaneRBAC(testParams()).Roles, "felis-api")
for _, v := range []string{"get", "list", "create", "patch"} {
// watch backs the informer cache the fleet reads come from.
for _, v := range []string{"get", "list", "watch", "create", "patch"} {
if !hasRule(mc, groupFelis, "minecraftservers", v) {
t.Errorf("felis-api must have minecraftservers:%s", v)
}
@@ -121,6 +122,11 @@ func TestAPIRole_MinecraftPowersExact(t *testing.T) {
if !hasRule(mc, groupCore, "secrets", "get") {
t.Error("felis-api must read RCON secrets (secrets:get) for console writes")
}
// The informer cache covers minecraftservers only; RCON secrets stay a direct
// Get by name, so no watch or list ever mirrors every secret into felis-api.
if hasRule(mc, groupCore, "secrets", "list") || hasRule(mc, groupCore, "secrets", "watch") {
t.Error("felis-api must NOT list or watch secrets (RCON reads are a direct Get by name)")
}
// WorldVolumeExists (backup/restore pre-gate) does a single direct PVC Get;
// nothing in felis-api lists or deletes claims.
if !hasRule(mc, groupCore, "persistentvolumeclaims", "get") {