Files
capsule/pkg/api/rbac/promotion_status_list.go
cc4fb45d70 feat: upstream enterprise preview (#1841)
feat: upstream enterprise preview

---------

Signed-off-by: Oliver Baehler <oliver@sudo-i.net>
Co-authored-by: CorentinPtrl <pitrel.corentin@gmail.com>
2026-05-28 00:58:58 +02:00

140 lines
2.8 KiB
Go

// Copyright 2020-2026 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0
package rbac
import (
"sort"
"strings"
)
// +kubebuilder:object:generate=true
type PromotionStatusListSpec []PromotionSpec
func (o *PromotionStatusListSpec) Upsert(newPromotion PromotionSpec) {
newPromotion.ClusterRoles = mergeSortedStrings(nil, newPromotion.ClusterRoles)
newPromotion.Targets = mergeSortedStrings(nil, newPromotion.Targets)
promotions := *o
for i := range promotions {
if !samePromotionIdentity(promotions[i], newPromotion) {
continue
}
promotions[i].ClusterRoles = mergeSortedStrings(promotions[i].ClusterRoles, newPromotion.ClusterRoles)
sort.Sort(GetPromotionByKindNameAndTargets(promotions))
*o = promotions
return
}
promotions = append(promotions, newPromotion)
sort.Sort(GetPromotionByKindNameAndTargets(promotions))
*o = promotions
}
func (o PromotionStatusListSpec) FindUser(name string, kind OwnerKind) (PromotionSpec, bool) {
result := PromotionSpec{
UserSpec: UserSpec{
Name: name,
Kind: kind,
},
}
found := false
for _, promotion := range o {
if promotion.Name != name || promotion.Kind != kind {
continue
}
found = true
result.ClusterRoles = mergeSortedStrings(result.ClusterRoles, promotion.ClusterRoles)
result.Targets = mergeSortedStrings(result.Targets, promotion.Targets)
}
if !found {
return PromotionSpec{}, false
}
return result, true
}
type GetPromotionByKindNameAndTargets PromotionStatusListSpec
func (b GetPromotionByKindNameAndTargets) Len() int {
return len(b)
}
func (b GetPromotionByKindNameAndTargets) Less(i, j int) bool {
return promotionLess(b[i], b[j])
}
func (b GetPromotionByKindNameAndTargets) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}
func promotionLess(a, b PromotionSpec) bool {
if a.Kind.String() != b.Kind.String() {
return a.Kind.String() < b.Kind.String()
}
if a.Name != b.Name {
return a.Name < b.Name
}
return stringSliceKey(a.Targets) < stringSliceKey(b.Targets)
}
func samePromotionIdentity(a, b PromotionSpec) bool {
return a.Kind == b.Kind &&
a.Name == b.Name &&
stringSliceKey(a.Targets) == stringSliceKey(b.Targets)
}
func stringSliceKey(values []string) string {
sorted := mergeSortedStrings(nil, values)
var key strings.Builder
for i, value := range sorted {
if i > 0 {
key.WriteString("\x00")
}
key.WriteString(value)
}
return key.String()
}
func mergeSortedStrings(existing []string, incoming []string) []string {
if len(existing) == 0 && len(incoming) == 0 {
return nil
}
values := make(map[string]struct{}, len(existing)+len(incoming))
for _, value := range existing {
values[value] = struct{}{}
}
for _, value := range incoming {
values[value] = struct{}{}
}
merged := make([]string, 0, len(values))
for value := range values {
merged = append(merged, value)
}
sort.Strings(merged)
return merged
}