// Copyright 2020-2026 Project Capsule Authors // SPDX-License-Identifier: Apache-2.0 package meta import ( "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type ManagedMetadata struct { labels map[string]struct{} annotations map[string]struct{} annotationPrefixes []string } func NewManagedMetadata( labels []string, annotations []string, ) ManagedMetadata { m := ManagedMetadata{ labels: stringSet( ResourcesLabel, TenantNameLabel, TenantLabel, NewTenantLabel, ResourcePoolLabel, GlobalResourceQuotaLabel, FreezeLabel, OwnerPromotionLabel, ServiceAccountPromotionLabel, CordonedLabel, CapsuleNameLabel, CreatedByCapsuleLabel, CustomResourcesLabel, NewManagedByCapsuleLabel, ManagedByCapsuleLabel, LimitRangeLabel, NetworkPolicyLabel, ResourceQuotaLabel, RuleQuotaLabel, RolebindingLabel, ), annotations: stringSet( ReleaseAnnotation, ReconcileAnnotation, AvailableIngressClassesAnnotation, AvailableIngressClassesRegexpAnnotation, AvailableStorageClassesAnnotation, AvailableStorageClassesRegexpAnnotation, AllowedRegistriesAnnotation, AllowedRegistriesRegexpAnnotation, ForbiddenNamespaceLabelsAnnotation, ForbiddenNamespaceLabelsRegexpAnnotation, ForbiddenNamespaceAnnotationsAnnotation, ForbiddenNamespaceAnnotationsRegexpAnnotation, ProtectedTenantAnnotation, ), annotationPrefixes: compactStrings( ResourceQuotaAnnotationPrefix, ResourceUsedAnnotationPrefix, ), } m.addLabels(labels...) m.addAnnotations(annotations...) return m } func (m ManagedMetadata) HasLabel(key string) bool { _, ok := m.labels[key] return ok } func (m ManagedMetadata) HasAnnotation(key string) bool { if _, ok := m.annotations[key]; ok { return true } for _, prefix := range m.annotationPrefixes { if strings.HasPrefix(key, prefix) { return true } } return false } func (m ManagedMetadata) addLabels(values ...string) { addStrings(m.labels, values...) } func (m ManagedMetadata) addAnnotations(values ...string) { addStrings(m.annotations, values...) } func addStrings(set map[string]struct{}, values ...string) { for _, value := range values { value = strings.TrimSpace(value) if value == "" { continue } set[value] = struct{}{} } } func stringSet(values ...string) map[string]struct{} { if len(values) == 0 { return nil } out := make(map[string]struct{}, len(values)) for _, value := range values { value = strings.TrimSpace(value) if value == "" { continue } out[value] = struct{}{} } return out } func compactStrings(values ...string) []string { if len(values) == 0 { return nil } out := make([]string, 0, len(values)) for _, value := range values { value = strings.TrimSpace(value) if value == "" { continue } out = append(out, value) } return out } type ObjectSkipRule struct { // Labels with values which indicate a skip condition. Labels map[string]string // Annotations with values which indicate a skip condition. Annotations map[string]string } func (s *ObjectSkipRule) ShouldSkip( labels map[string]string, annotations map[string]string, ) bool { if s == nil { return false } for key, expected := range s.Labels { value, ok := labels[key] if !ok || value != expected { return false } } for key, expected := range s.Annotations { value, ok := annotations[key] if !ok || value != expected { return false } } return len(s.Labels) > 0 || len(s.Annotations) > 0 } func DefaultObjectSkipRules() []ObjectSkipRule { return []ObjectSkipRule{ { Labels: map[string]string{ NewManagedByCapsuleLabel: ValueController, }, }, { Labels: map[string]string{ NewManagedByCapsuleLabel: ValueControllerResources, }, }, } } func ShouldSkipObjectByRules( obj *metav1.PartialObjectMetadata, rules []ObjectSkipRule, ) bool { if obj == nil || len(rules) == 0 { return false } labels := obj.GetLabels() annotations := obj.GetAnnotations() for _, rule := range rules { if rule.ShouldSkip(labels, annotations) { return true } } return false }