Files
capsule/pkg/api/rbac/owner_status_list.go
Oliver BählerandGitHub 99e05220ab feat: implement performance optimizations (#2045)
* feat: implement performance optimizations

---------

Signed-off-by: Oliver Baehler <oliver@sudo-i.net>
2026-07-21 16:27:29 +02:00

120 lines
2.4 KiB
Go

// Copyright 2020-2026 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0
package rbac
import (
"sort"
)
// +kubebuilder:object:generate=true
type OwnerStatusListSpec []CoreOwnerSpec
func (o *OwnerStatusListSpec) Upsert(
newOwner CoreOwnerSpec,
) {
owners := *o
// Ensure slice is sorted before binary search
sort.Sort(GetByKindAndName(owners))
less := func(a, b CoreOwnerSpec) bool {
if a.Kind.String() != b.Kind.String() {
return a.Kind.String() < b.Kind.String()
}
return a.Name < b.Name
}
// Find the first index where owners[i] >= newOwner
idx := sort.Search(len(owners), func(i int) bool {
return !less(owners[i], newOwner)
})
// If we found an exact match (same Kind + Name), merge ClusterRoles
if idx < len(owners) && !less(owners[idx], newOwner) && !less(newOwner, owners[idx]) {
existing := &owners[idx]
roleSet := make(map[string]struct{}, len(existing.ClusterRoles))
for _, r := range existing.ClusterRoles {
roleSet[r] = struct{}{}
}
for _, r := range newOwner.ClusterRoles {
if _, ok := roleSet[r]; !ok {
existing.ClusterRoles = append(existing.ClusterRoles, r)
roleSet[r] = struct{}{}
}
}
sort.Strings(existing.ClusterRoles)
*o = owners
return
}
// Not found: append and keep sorted
owners = append(owners, newOwner)
sort.Sort(GetByKindAndName(owners))
*o = owners
}
func (o OwnerStatusListSpec) IsOwner(name string, groups []string) bool {
var groupSet map[string]struct{}
if len(groups) > 0 {
groupSet = make(map[string]struct{}, len(groups))
for _, g := range groups {
groupSet[g] = struct{}{}
}
}
for _, owner := range o {
switch owner.Kind {
case UserOwner, ServiceAccountOwner:
if name == owner.Name {
return true
}
case GroupOwner:
if groupSet == nil {
continue
}
if _, ok := groupSet[owner.Name]; ok {
return true
}
}
}
return false
}
func (o OwnerStatusListSpec) FindOwner(name string, kind OwnerKind) (CoreOwnerSpec, bool) {
for _, owner := range o {
if owner.Kind == kind && owner.Name == name {
return owner, true
}
}
return CoreOwnerSpec{}, false
}
type GetByKindAndName OwnerStatusListSpec
func (b GetByKindAndName) Len() int {
return len(b)
}
func (b GetByKindAndName) Less(i, j int) bool {
if b[i].Kind.String() != b[j].Kind.String() {
return b[i].Kind.String() < b[j].Kind.String()
}
return b[i].Name < b[j].Name
}
func (b GetByKindAndName) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}