From 1c146bdb6c50f6b87ce6419c0c73d2f0d250a185 Mon Sep 17 00:00:00 2001 From: Sukuna0007Abhi Date: Wed, 10 Jun 2026 21:00:34 +0530 Subject: [PATCH 1/2] fix(webhook): merge dataset annotations in multi-round FUSE injection Signed-off-by: Sukuna0007Abhi --- .../dataset_usage_injector.go | 24 +++++++++++++++---- .../dataset_usage_injector_test.go | 4 ++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go index f5c0149d3f4..40b1976ab95 100644 --- a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go +++ b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go @@ -33,7 +33,6 @@ func NewPlugin(c client.Client, args string) (api.MutatingHandler, error) { }, nil } -// TODO: Support cases where fuse sidecars are injected in multi-round. Currently, only dataset names in the first round will be recorded. func (injector *DatasetUsageInjector) Mutate(pod *corev1.Pod, runtimeInfos map[string]base.RuntimeInfoInterface) (shouldStop bool, err error) { if len(runtimeInfos) == 0 { return false, nil @@ -44,13 +43,30 @@ func (injector *DatasetUsageInjector) Mutate(pod *corev1.Pod, runtimeInfos map[s podName = pod.GenerateName } - datasetsInUse := make([]string, 0, len(runtimeInfos)) + annotationKey := common.LabelAnnotationDatasetsInUse + + datasetsInUseMap := make(map[string]struct{}) + + // 1. Read existing datasets from annotation + if existingVal, exists := pod.Annotations[annotationKey]; exists && len(existingVal) > 0 { + existingDatasets := strings.Split(existingVal, ",") + for _, ds := range existingDatasets { + datasetsInUseMap[strings.TrimSpace(ds)] = struct{}{} + } + } + + // 2. Add new datasets from current round for _, runtimeInfo := range runtimeInfos { - datasetsInUse = append(datasetsInUse, runtimeInfo.GetName()) + datasetsInUseMap[runtimeInfo.GetName()] = struct{}{} + } + + // 3. Convert map to sorted slice + datasetsInUse := make([]string, 0, len(datasetsInUseMap)) + for ds := range datasetsInUseMap { + datasetsInUse = append(datasetsInUse, ds) } slices.Sort(datasetsInUse) - annotationKey := common.LabelAnnotationDatasetsInUse annotationValue := strings.Join(datasetsInUse, ",") log.Info("Injecting dataset usage annotation to pod", diff --git a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go index 1e5d4db51f3..dc5ecbc5e45 100644 --- a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go +++ b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go @@ -169,7 +169,7 @@ var _ = Describe("DatasetUsageInjector", func() { }) Context("when pod has different annotation value", func() { - It("should update the annotation", func() { + It("should merge the existing annotation with the new one", func() { pod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "test-update", @@ -188,7 +188,7 @@ var _ = Describe("DatasetUsageInjector", func() { Expect(err).NotTo(HaveOccurred()) Expect(shouldStop).To(BeFalse()) - Expect(pod.Annotations[common.LabelAnnotationDatasetsInUse]).To(Equal("demo-dataset-1")) + Expect(pod.Annotations[common.LabelAnnotationDatasetsInUse]).To(Equal("demo-dataset-1,old-dataset")) }) }) }) From 7931adbc3072615699727d758277badcd01c473f Mon Sep 17 00:00:00 2001 From: Sukuna0007Abhi Date: Sun, 14 Jun 2026 13:22:36 +0530 Subject: [PATCH 2/2] fix(webhook): filter empty strings in dataset usage injector and add partial overlap test Signed-off-by: Sukuna0007Abhi --- .../dataset_usage_injector.go | 5 +++- .../dataset_usage_injector_test.go | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go index 40b1976ab95..fdfb6dbb1b5 100644 --- a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go +++ b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector.go @@ -51,7 +51,10 @@ func (injector *DatasetUsageInjector) Mutate(pod *corev1.Pod, runtimeInfos map[s if existingVal, exists := pod.Annotations[annotationKey]; exists && len(existingVal) > 0 { existingDatasets := strings.Split(existingVal, ",") for _, ds := range existingDatasets { - datasetsInUseMap[strings.TrimSpace(ds)] = struct{}{} + trimmed := strings.TrimSpace(ds) + if trimmed != "" { + datasetsInUseMap[trimmed] = struct{}{} + } } } diff --git a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go index dc5ecbc5e45..3dd0756db77 100644 --- a/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go +++ b/pkg/webhook/plugins/datasetusageinjector/dataset_usage_injector_test.go @@ -191,6 +191,31 @@ var _ = Describe("DatasetUsageInjector", func() { Expect(pod.Annotations[common.LabelAnnotationDatasetsInUse]).To(Equal("demo-dataset-1,old-dataset")) }) }) + + Context("when pod has partially overlapping annotations", func() { + It("should deduplicate and merge the existing annotation with the new one", func() { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-partial-overlap", + Namespace: "fluid-test", + Annotations: map[string]string{ + common.LabelAnnotationDatasetsInUse: "demo-dataset-2,demo-dataset-3", + }, + }, + } + + runtimeInfos := map[string]base.RuntimeInfoInterface{ + "demo-dataset-1": runtimeInfo1, + "demo-dataset-2": runtimeInfo2, + } + + shouldStop, err := injector.Mutate(pod, runtimeInfos) + Expect(err).NotTo(HaveOccurred()) + Expect(shouldStop).To(BeFalse()) + + Expect(pod.Annotations[common.LabelAnnotationDatasetsInUse]).To(Equal("demo-dataset-1,demo-dataset-2,demo-dataset-3")) + }) + }) }) Describe("GetName", func() {