Skip to content

Commit ba8257b

Browse files
committed
Refactor: Improve resource cleanup logic and add utility functions for comparison
1 parent b4e56a1 commit ba8257b

3 files changed

Lines changed: 365 additions & 114 deletions

File tree

.github/workflows/check-code-gen.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ jobs:
3333

3434
- name: Check dependencies Generation 🧪
3535
run: |
36-
make generate manifests bundle
36+
make generate manifests
3737
git diff --ignore-matching-lines='.*createdAt:.*' --exit-code

internal/controller/overcommitclass/overcommitclass_controller.go

Lines changed: 135 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313

1414
resources "github.com/InditexTech/k8s-overcommit-operator/internal/resources"
1515
"github.com/InditexTech/k8s-overcommit-operator/internal/utils"
16-
corev1 "k8s.io/api/core/v1"
1716
"k8s.io/apimachinery/pkg/runtime"
1817
ctrl "sigs.k8s.io/controller-runtime"
1918
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -52,112 +51,6 @@ func (r *OvercommitClassReconciler) SetupWithManager(mgr ctrl.Manager) error {
5251
Complete(r)
5352
}
5453

55-
// cleanupResources ensures that all resources associated with the OvercommitClass CR are deleted.
56-
func (r *OvercommitClassReconciler) cleanupResources(ctx context.Context, overcommitClass *overcommit.OvercommitClass) error {
57-
logger := log.FromContext(ctx)
58-
logger.Info("Cleaning up resources associated with OvercommitClass CR", "name", overcommitClass.Name)
59-
60-
// Delete Deployment
61-
deployment := resources.CreateDeployment(*overcommitClass)
62-
if deployment != nil {
63-
err := r.Delete(ctx, deployment)
64-
if err != nil && client.IgnoreNotFound(err) != nil {
65-
logger.Error(err, "Failed to delete Deployment")
66-
return err
67-
}
68-
}
69-
70-
// Delete Service
71-
service := resources.CreateService(overcommitClass.Name)
72-
if service != nil {
73-
err := r.Delete(ctx, service)
74-
if err != nil && client.IgnoreNotFound(err) != nil {
75-
logger.Error(err, "Failed to delete Service")
76-
return err
77-
}
78-
}
79-
80-
// Delete Certificate
81-
certificate := resources.CreateCertificate(overcommitClass.Name, *service)
82-
if certificate != nil {
83-
err := r.Delete(ctx, certificate)
84-
if err != nil && client.IgnoreNotFound(err) != nil {
85-
logger.Error(err, "Failed to delete Certificate")
86-
return err
87-
}
88-
}
89-
90-
// Delete MutatingWebhookConfiguration
91-
label, err := utils.GetOvercommitLabel(ctx, r.Client)
92-
if err != nil {
93-
logger.Error(err, "Failed to get Overcommit label")
94-
return err
95-
}
96-
97-
webhookConfig := resources.CreateMutatingWebhookConfiguration(*overcommitClass, *service, *certificate, label)
98-
if webhookConfig != nil {
99-
err := r.Delete(ctx, webhookConfig)
100-
if err != nil && client.IgnoreNotFound(err) != nil {
101-
logger.Error(err, "Failed to delete MutatingWebhookConfiguration")
102-
return err
103-
}
104-
}
105-
106-
logger.Info("Successfully cleaned up resources for OvercommitClass", "name", overcommitClass.Name)
107-
return nil
108-
}
109-
110-
// envVarsEqual compares two slices of environment variables to see if they're equal
111-
func envVarsEqual(a, b []corev1.EnvVar) bool {
112-
if len(a) != len(b) {
113-
return false
114-
}
115-
116-
// Create maps for easier comparison
117-
mapA := make(map[string]string)
118-
mapB := make(map[string]string)
119-
120-
for _, env := range a {
121-
mapA[env.Name] = env.Value
122-
}
123-
124-
for _, env := range b {
125-
mapB[env.Name] = env.Value
126-
}
127-
128-
// Compare maps
129-
for key, valueA := range mapA {
130-
if valueB, exists := mapB[key]; !exists || valueA != valueB {
131-
return false
132-
}
133-
}
134-
135-
return true
136-
}
137-
138-
// mapsEqual compares two string maps to see if they're equal
139-
func mapsEqual(a, b map[string]string) bool {
140-
// Handle nil cases
141-
if a == nil && b == nil {
142-
return true
143-
}
144-
if a == nil || b == nil {
145-
return false
146-
}
147-
148-
if len(a) != len(b) {
149-
return false
150-
}
151-
152-
for key, valueA := range a {
153-
if valueB, exists := b[key]; !exists || valueA != valueB {
154-
return false
155-
}
156-
}
157-
158-
return true
159-
}
160-
16154
func (r *OvercommitClassReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
16255
logger := log.FromContext(ctx)
16356
logger.Info("Starting reconciliation", "name", req.Name, "namespace", req.Namespace, "time", time.Now().Format("15:04:05"))
@@ -323,11 +216,54 @@ func (r *OvercommitClassReconciler) Reconcile(ctx context.Context, req ctrl.Requ
323216

324217
// Reconcile Service with improved logic
325218
_, err = controllerutil.CreateOrUpdate(ctx, r.Client, service, func() error {
326-
// Only update spec if this is a new resource
219+
// Regenerate the desired service spec
220+
updatedService := resources.CreateService(overcommitClass.Name)
221+
222+
// Only update if there are actual differences
327223
if service.CreationTimestamp.IsZero() {
328-
updatedService := resources.CreateService(overcommitClass.Name)
224+
// New service, set everything
329225
service.Spec = updatedService.Spec
226+
service.ObjectMeta.Labels = updatedService.ObjectMeta.Labels
227+
service.ObjectMeta.Annotations = updatedService.ObjectMeta.Annotations
330228
return controllerutil.SetControllerReference(overcommitClass, service, r.Scheme)
229+
} else {
230+
// Existing service, only update specific fields if needed
231+
updated := false
232+
233+
// Check if selector changed
234+
if !mapsEqual(updatedService.Spec.Selector, service.Spec.Selector) {
235+
service.Spec.Selector = updatedService.Spec.Selector
236+
updated = true
237+
}
238+
239+
// Check if ports changed
240+
if !portsEqual(updatedService.Spec.Ports, service.Spec.Ports) {
241+
service.Spec.Ports = updatedService.Spec.Ports
242+
updated = true
243+
}
244+
245+
// Check if service type changed
246+
if updatedService.Spec.Type != service.Spec.Type {
247+
service.Spec.Type = updatedService.Spec.Type
248+
updated = true
249+
}
250+
251+
// Update annotations if they changed
252+
if !mapsEqual(updatedService.ObjectMeta.Annotations, service.ObjectMeta.Annotations) {
253+
service.ObjectMeta.Annotations = updatedService.ObjectMeta.Annotations
254+
updated = true
255+
}
256+
257+
// Update labels if they changed
258+
if !mapsEqual(updatedService.ObjectMeta.Labels, service.ObjectMeta.Labels) {
259+
service.ObjectMeta.Labels = updatedService.ObjectMeta.Labels
260+
updated = true
261+
}
262+
263+
// Only set controller reference if we actually updated something
264+
if updated {
265+
return controllerutil.SetControllerReference(overcommitClass, service, r.Scheme)
266+
}
331267
}
332268
return nil
333269
})
@@ -338,11 +274,55 @@ func (r *OvercommitClassReconciler) Reconcile(ctx context.Context, req ctrl.Requ
338274

339275
// Reconcile Certificate with improved logic
340276
_, err = controllerutil.CreateOrUpdate(ctx, r.Client, certificate, func() error {
341-
// Only update spec if this is a new resource
277+
// Regenerate the desired certificate spec
278+
updatedCertificate := resources.CreateCertificate(overcommitClass.Name, *service)
279+
280+
// Only update if there are actual differences
342281
if certificate.CreationTimestamp.IsZero() {
343-
updatedCertificate := resources.CreateCertificate(overcommitClass.Name, *service)
282+
// New certificate, set everything
344283
certificate.Spec = updatedCertificate.Spec
284+
certificate.ObjectMeta.Labels = updatedCertificate.ObjectMeta.Labels
285+
certificate.ObjectMeta.Annotations = updatedCertificate.ObjectMeta.Annotations
345286
return controllerutil.SetControllerReference(overcommitClass, certificate, r.Scheme)
287+
} else {
288+
// Existing certificate, only update specific fields if needed
289+
updated := false
290+
291+
// Check if DNS names changed
292+
if !slicesEqual(updatedCertificate.Spec.DNSNames, certificate.Spec.DNSNames) {
293+
certificate.Spec.DNSNames = updatedCertificate.Spec.DNSNames
294+
updated = true
295+
}
296+
297+
// Check if issuer ref changed
298+
if updatedCertificate.Spec.IssuerRef.Name != certificate.Spec.IssuerRef.Name ||
299+
updatedCertificate.Spec.IssuerRef.Kind != certificate.Spec.IssuerRef.Kind {
300+
certificate.Spec.IssuerRef = updatedCertificate.Spec.IssuerRef
301+
updated = true
302+
}
303+
304+
// Check if secret name changed
305+
if updatedCertificate.Spec.SecretName != certificate.Spec.SecretName {
306+
certificate.Spec.SecretName = updatedCertificate.Spec.SecretName
307+
updated = true
308+
}
309+
310+
// Update annotations if they changed
311+
if !mapsEqual(updatedCertificate.ObjectMeta.Annotations, certificate.ObjectMeta.Annotations) {
312+
certificate.ObjectMeta.Annotations = updatedCertificate.ObjectMeta.Annotations
313+
updated = true
314+
}
315+
316+
// Update labels if they changed
317+
if !mapsEqual(updatedCertificate.ObjectMeta.Labels, certificate.ObjectMeta.Labels) {
318+
certificate.ObjectMeta.Labels = updatedCertificate.ObjectMeta.Labels
319+
updated = true
320+
}
321+
322+
// Only set controller reference if we actually updated something
323+
if updated {
324+
return controllerutil.SetControllerReference(overcommitClass, certificate, r.Scheme)
325+
}
346326
}
347327
return nil
348328
})
@@ -353,12 +333,54 @@ func (r *OvercommitClassReconciler) Reconcile(ctx context.Context, req ctrl.Requ
353333

354334
// Reconcile MutatingWebhookConfiguration with improved logic
355335
_, err = controllerutil.CreateOrUpdate(ctx, r.Client, webhookConfig, func() error {
356-
// Only update webhooks if this is a new resource
336+
// Regenerate the desired webhook configuration
337+
updatedWebhookConfig := resources.CreateMutatingWebhookConfiguration(*overcommitClass, *service, *certificate, label)
338+
339+
// Only update if there are actual differences
357340
if webhookConfig.CreationTimestamp.IsZero() {
358-
updatedWebhookConfig := resources.CreateMutatingWebhookConfiguration(*overcommitClass, *service, *certificate, label)
341+
// New webhook config, set everything
359342
webhookConfig.Annotations = updatedWebhookConfig.Annotations
343+
webhookConfig.Labels = updatedWebhookConfig.Labels
360344
webhookConfig.Webhooks = updatedWebhookConfig.Webhooks
361345
return controllerutil.SetControllerReference(overcommitClass, webhookConfig, r.Scheme)
346+
} else {
347+
// Existing webhook config, only update specific fields if needed
348+
updated := false
349+
350+
// Update annotations if they changed
351+
if !mapsEqual(updatedWebhookConfig.Annotations, webhookConfig.Annotations) {
352+
webhookConfig.Annotations = updatedWebhookConfig.Annotations
353+
updated = true
354+
}
355+
356+
// Update labels if they changed
357+
if !mapsEqual(updatedWebhookConfig.Labels, webhookConfig.Labels) {
358+
webhookConfig.Labels = updatedWebhookConfig.Labels
359+
updated = true
360+
}
361+
362+
// Check if webhooks changed (simplified comparison)
363+
if len(updatedWebhookConfig.Webhooks) != len(webhookConfig.Webhooks) {
364+
webhookConfig.Webhooks = updatedWebhookConfig.Webhooks
365+
updated = true
366+
} else {
367+
// Compare each webhook
368+
for i, updatedWebhook := range updatedWebhookConfig.Webhooks {
369+
if i < len(webhookConfig.Webhooks) {
370+
currentWebhook := webhookConfig.Webhooks[i]
371+
if webhookChanged(updatedWebhook, currentWebhook) {
372+
webhookConfig.Webhooks = updatedWebhookConfig.Webhooks
373+
updated = true
374+
break
375+
}
376+
}
377+
}
378+
}
379+
380+
// Only set controller reference if we actually updated something
381+
if updated {
382+
return controllerutil.SetControllerReference(overcommitClass, webhookConfig, r.Scheme)
383+
}
362384
}
363385
return nil
364386
})

0 commit comments

Comments
 (0)