From c5553225f9b5544cd050db6ce5db1b05a725c3d8 Mon Sep 17 00:00:00 2001 From: Niklas Voss Date: Mon, 21 Oct 2024 13:20:27 +0200 Subject: [PATCH] Merge into local spec to keep values set by crossplane --- controller/controller.go | 39 +++++++++++++++++++++++++++------------ main.go | 1 + 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/controller/controller.go b/controller/controller.go index b874bef..d39fe15 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -126,6 +126,8 @@ type Reconciler struct { LocalPropagationPolicy client.PropagationPolicy // ConcurrentReconciles sets the number of concurrent reconciles. ConcurrentReconciles int + // + MergeIntoLocalSpec bool } // Reconcile is part of the main kubernetes reconciliation loop which aims to @@ -479,24 +481,33 @@ func (r *Reconciler) syncLocal(ctx context.Context, localNs *corev1.Namespace, l // Update is preferable to Patch, so we guarantee that spec never diverges. // This also slows down spec updates in exchange for more granular status updates. op, err := controllerutil.CreateOrUpdate(ctx, r.Client, local, func() error { - ok := setField(local, fieldSpec, getField(remote, fieldSpec)) + remoteSpec := getField(remote, fieldSpec) + ok := false + if r.MergeIntoLocalSpec { + localSpec := getField(local, fieldSpec) + for k, v := range remoteSpec { + localSpec[k] = v + } + } else { + ok = setField(local, fieldSpec, remoteSpec) + } if !ok { return errors.New("cannot set spec, invalid struct") } anno := remote.GetAnnotations() + // for k, v := range local.GetAnnotations() { + // anno[k] = v + // } delete(anno, AnnotationRemoteGeneration) delete(anno, AnnotationLocalGeneration) - for k, v := range local.GetAnnotations() { - anno[k] = v - } local.SetAnnotations(anno) labels := remote.GetLabels() - if labels == nil { - labels = map[string]string{} - } - for k, v := range local.GetLabels() { - labels[k] = v - } + // if labels == nil { + // labels = map[string]string{} + // } + // for k, v := range local.GetLabels() { + // labels[k] = v + // } local.SetLabels(labels) return nil }) @@ -661,8 +672,12 @@ func objHash(o any) (string, error) { } // getField retries a field from a struct or struct pointer using reflection. -func getField(s *unstructured.Unstructured, field string) any { - return s.Object[field] +func getField(s *unstructured.Unstructured, field string) map[string]any { + m, _, _ := unstructured.NestedMap(s.Object, field) + if m == nil { + return map[string]any{} + } + return m } // setField sets a field on a struct pointer. diff --git a/main.go b/main.go index 7d8f89a..6a59ad7 100644 --- a/main.go +++ b/main.go @@ -150,6 +150,7 @@ func main() { LocalSecretNames: localSecretNames, LocalPropagationPolicy: client.PropagationPolicy(metav1.DeletePropagationForeground), ConcurrentReconciles: 1, + MergeIntoLocalSpec: true, } if err := syncReconciler.SetupWithManager(mgr); err != nil {