Skip to content

Commit fa5156c

Browse files
committed
preserve external controller annotations for deployment and daemonSet
1 parent 3424d94 commit fa5156c

File tree

2 files changed

+404
-49
lines changed

2 files changed

+404
-49
lines changed

internal/controller/provisioner/setter.go

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,18 @@ func objectSpecSetter(object client.Object) controllerutil.MutateFn {
4040
return nil
4141
}
4242

43+
const (
44+
managedKeysAnnotation = "gateway.nginx.org/internal-managed-annotation-keys"
45+
)
46+
4347
func deploymentSpecSetter(
4448
deployment *appsv1.Deployment,
4549
spec appsv1.DeploymentSpec,
4650
objectMeta metav1.ObjectMeta,
4751
) controllerutil.MutateFn {
4852
return func() error {
4953
deployment.Labels = objectMeta.Labels
50-
deployment.Annotations = objectMeta.Annotations
54+
deployment.Annotations = mergeAnnotations(deployment.Annotations, objectMeta.Annotations, managedKeysAnnotation)
5155
deployment.Spec = spec
5256
return nil
5357
}
@@ -73,7 +77,7 @@ func daemonSetSpecSetter(
7377
) controllerutil.MutateFn {
7478
return func() error {
7579
daemonSet.Labels = objectMeta.Labels
76-
daemonSet.Annotations = objectMeta.Annotations
80+
daemonSet.Annotations = mergeAnnotations(daemonSet.Annotations, objectMeta.Annotations, managedKeysAnnotation)
7781
daemonSet.Spec = spec
7882
return nil
7983
}
@@ -85,54 +89,8 @@ func serviceSpecSetter(
8589
objectMeta metav1.ObjectMeta,
8690
) controllerutil.MutateFn {
8791
return func() error {
88-
const managedKeysAnnotation = "gateway.nginx.org/internal-managed-annotation-keys"
89-
90-
// Track which annotation keys NGF currently manages
91-
currentManagedKeys := make(map[string]bool)
92-
for k := range objectMeta.Annotations {
93-
currentManagedKeys[k] = true
94-
}
95-
96-
// Get previously managed keys from existing service
97-
var previousManagedKeys map[string]bool
98-
if prevKeysStr, ok := service.Annotations[managedKeysAnnotation]; ok {
99-
previousManagedKeys = make(map[string]bool)
100-
for _, k := range strings.Split(prevKeysStr, ",") {
101-
if k != "" {
102-
previousManagedKeys[k] = true
103-
}
104-
}
105-
}
106-
107-
// Start with existing annotations (preserves external controller annotations)
108-
mergedAnnotations := make(map[string]string)
109-
for k, v := range service.Annotations {
110-
// Skip the internal tracking annotation
111-
if k == managedKeysAnnotation {
112-
continue
113-
}
114-
// Remove annotations that NGF previously managed but no longer wants
115-
if previousManagedKeys != nil && previousManagedKeys[k] && !currentManagedKeys[k] {
116-
continue // Remove this annotation
117-
}
118-
mergedAnnotations[k] = v
119-
}
120-
121-
// Apply NGF-managed annotations (take precedence)
122-
maps.Copy(mergedAnnotations, objectMeta.Annotations)
123-
124-
// Store current managed keys for next reconciliation
125-
if len(currentManagedKeys) > 0 {
126-
var managedKeysList []string
127-
for k := range currentManagedKeys {
128-
managedKeysList = append(managedKeysList, k)
129-
}
130-
slices.Sort(managedKeysList) // Sort for deterministic output
131-
mergedAnnotations[managedKeysAnnotation] = strings.Join(managedKeysList, ",")
132-
}
133-
13492
service.Labels = objectMeta.Labels
135-
service.Annotations = mergedAnnotations
93+
service.Annotations = mergeAnnotations(service.Annotations, objectMeta.Annotations, managedKeysAnnotation)
13694
service.Spec = spec
13795
return nil
13896
}
@@ -210,3 +168,54 @@ func roleBindingSpecSetter(
210168
return nil
211169
}
212170
}
171+
172+
func mergeAnnotations(existing, desired map[string]string, trackingKey string) map[string]string {
173+
desiredKeys := make(map[string]struct{}, len(desired))
174+
for key := range desired {
175+
desiredKeys[key] = struct{}{}
176+
}
177+
178+
previousKeys := make(map[string]struct{}, len(existing))
179+
if existing != nil {
180+
if prev, ok := existing[trackingKey]; ok {
181+
for splitKey := range strings.SplitSeq(prev, ",") {
182+
if splitKey != "" {
183+
previousKeys[splitKey] = struct{}{}
184+
}
185+
}
186+
}
187+
}
188+
189+
annotations := make(map[string]string)
190+
191+
// Start with existing annotations (preserves external controller annotations)
192+
for key, value := range existing {
193+
if key == trackingKey {
194+
continue
195+
}
196+
197+
// if this key was previously managed and is no longer desired, drop it
198+
if _, wasManaged := previousKeys[key]; wasManaged {
199+
if _, stillDesired := desiredKeys[key]; !stillDesired {
200+
continue
201+
}
202+
}
203+
204+
annotations[key] = value
205+
}
206+
207+
// Apply desired annotations (NGF-managed wins)
208+
maps.Copy(annotations, desired)
209+
210+
// Store current managed keys
211+
if len(desiredKeys) > 0 {
212+
keys := make([]string, 0, len(desiredKeys))
213+
for key := range desiredKeys {
214+
keys = append(keys, key)
215+
}
216+
slices.Sort(keys)
217+
annotations[trackingKey] = strings.Join(keys, ",")
218+
}
219+
220+
return annotations
221+
}

0 commit comments

Comments
 (0)