karmada/pkg/util/annotation.go

100 lines
3.5 KiB
Go

package util
import (
"sort"
"strings"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/sets"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
)
// MergeAnnotation adds annotation for the given object, keep the value unchanged if key exist.
func MergeAnnotation(obj *unstructured.Unstructured, annotationKey string, annotationValue string) {
objectAnnotation := obj.GetAnnotations()
if objectAnnotation == nil {
objectAnnotation = make(map[string]string, 1)
}
if _, exist := objectAnnotation[annotationKey]; !exist {
objectAnnotation[annotationKey] = annotationValue
obj.SetAnnotations(objectAnnotation)
}
}
// ReplaceAnnotation adds annotation for the given object, replace the value if key exist.
func ReplaceAnnotation(obj *unstructured.Unstructured, annotationKey string, annotationValue string) {
objectAnnotation := obj.GetAnnotations()
if objectAnnotation == nil {
objectAnnotation = make(map[string]string, 1)
}
objectAnnotation[annotationKey] = annotationValue
obj.SetAnnotations(objectAnnotation)
}
// RetainAnnotations merges the annotations that added by controllers running
// in member cluster to avoid overwriting.
// Following keys will be ignored if :
// - the keys were previous propagated to member clusters(that are tracked
// by "resourcetemplate.karmada.io/managed-annotations" annotation in observed)
// but have been removed from Karmada control plane(don't exist in desired anymore).
// - the keys that exist in both desired and observed even those been accidentally modified
// in member clusters.
func RetainAnnotations(desired *unstructured.Unstructured, observed *unstructured.Unstructured) {
objectAnnotation := desired.GetAnnotations()
if objectAnnotation == nil {
objectAnnotation = make(map[string]string, 0)
}
deletedAnnotationKeys := getDeletedAnnotationKeys(desired, observed)
for key, value := range observed.GetAnnotations() {
if deletedAnnotationKeys.Has(key) {
continue
}
if _, exist := objectAnnotation[key]; exist {
continue
}
objectAnnotation[key] = value
}
if len(objectAnnotation) > 0 {
desired.SetAnnotations(objectAnnotation)
}
}
// GetAnnotationValue retrieves the value via 'annotationKey' (if it exists), otherwise an empty string is returned.
func GetAnnotationValue(annotations map[string]string, annotationKey string) string {
if annotations == nil {
return ""
}
return annotations[annotationKey]
}
func getDeletedAnnotationKeys(desired, observed *unstructured.Unstructured) sets.Set[string] {
recordKeys := sets.New[string](strings.Split(observed.GetAnnotations()[workv1alpha2.ManagedAnnotation], ",")...)
for key := range desired.GetAnnotations() {
recordKeys.Delete(key)
}
return recordKeys
}
// RecordManagedAnnotations sets or updates the annotation(resourcetemplate.karmada.io/managed-annotations)
// to record the annotation keys.
func RecordManagedAnnotations(object *unstructured.Unstructured) {
annotations := object.GetAnnotations()
if annotations == nil {
annotations = make(map[string]string, 1)
}
// record annotations.
managedKeys := []string{workv1alpha2.ManagedAnnotation, workv1alpha2.ManagedLabels}
for key := range annotations {
if key == workv1alpha2.ManagedAnnotation || key == workv1alpha2.ManagedLabels {
continue
}
managedKeys = append(managedKeys, key)
}
sort.Strings(managedKeys)
annotations[workv1alpha2.ManagedAnnotation] = strings.Join(managedKeys, ",")
object.SetAnnotations(annotations)
}