mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-21 21:47:16 +00:00
feat: upstream enterprise preview --------- Signed-off-by: Oliver Baehler <oliver@sudo-i.net> Co-authored-by: CorentinPtrl <pitrel.corentin@gmail.com>
140 lines
2.8 KiB
Go
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
|
|
}
|