Files
capsule/pkg/api/owner_status_list.go
renovate[bot] eb8d2b6076 chore(deps): update dependency golangci/golangci-lint to v2.8.0 (#1823)
* chore(deps): update dependency golangci/golangci-lint to v2.8.0

* chore(deps): update dependency golangci/golangci-lint to v2.8.0

Signed-off-by: Hristo Hristov <me@hhristov.info>

* chore(deps): update dependency golangci/golangci-lint to v2.8.0

Signed-off-by: Hristo Hristov <me@hhristov.info>

* chore(deps): update dependency golangci/golangci-lint to v2.8.0

Signed-off-by: Hristo Hristov <me@hhristov.info>

---------

Signed-off-by: Hristo Hristov <me@hhristov.info>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Hristo Hristov <me@hhristov.info>
2026-01-08 15:43:32 +02:00

140 lines
2.8 KiB
Go

// Copyright 2020-2026 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0
package api
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
}
//nolint:dupl
func (o OwnerStatusListSpec) FindOwner(name string, kind OwnerKind) (CoreOwnerSpec, bool) {
// Sort in-place by (Kind.String(), Name).
sort.Sort(GetByKindAndName(o))
targetKind := kind.String()
n := len(o)
idx := sort.Search(n, func(i int) bool {
ki := o[i].Kind.String()
switch {
case ki > targetKind:
return true
case ki < targetKind:
return false
default:
return o[i].Name >= name
}
})
if idx < n &&
o[idx].Kind.String() == targetKind &&
o[idx].Name == name {
return o[idx], 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]
}