@@ -324,6 +324,47 @@ func (p *DefaultDiffProcessor) DiffSingleResource(ctx context.Context, res *un.U
324324// ProcessNestedXRs recursively processes composed resources that are themselves XRs.
325325// It checks each composed resource to see if it's an XR, and if so, processes it through
326326// its own composition pipeline to get the full tree of diffs.
327+ // findExistingNestedXR locates an existing nested XR in the observed resources by matching
328+ // the composition-resource-name annotation and kind.
329+ func findExistingNestedXR (nestedXR * un.Unstructured , observedResources []cpd.Unstructured ) * un.Unstructured {
330+ compositionResourceName := nestedXR .GetAnnotations ()["crossplane.io/composition-resource-name" ]
331+ if compositionResourceName == "" {
332+ return nil
333+ }
334+
335+ for _ , obs := range observedResources {
336+ obsUnstructured := & un.Unstructured {Object : obs .UnstructuredContent ()}
337+ obsCompResName := obsUnstructured .GetAnnotations ()["crossplane.io/composition-resource-name" ]
338+
339+ // Match by composition-resource-name annotation and kind
340+ if obsCompResName == compositionResourceName && obsUnstructured .GetKind () == nestedXR .GetKind () {
341+ return obsUnstructured
342+ }
343+ }
344+
345+ return nil
346+ }
347+
348+ // preserveNestedXRIdentity updates the nested XR to preserve the identity of an existing XR
349+ // by copying its name, generateName, and composite label.
350+ func preserveNestedXRIdentity (nestedXR , existingNestedXR * un.Unstructured ) {
351+ // Preserve the actual cluster name
352+ nestedXR .SetName (existingNestedXR .GetName ())
353+ nestedXR .SetGenerateName (existingNestedXR .GetGenerateName ())
354+
355+ // Preserve the composite label so child resources get matched correctly
356+ if labels := existingNestedXR .GetLabels (); labels != nil {
357+ if compositeLabel , exists := labels ["crossplane.io/composite" ]; exists {
358+ nestedXRLabels := nestedXR .GetLabels ()
359+ if nestedXRLabels == nil {
360+ nestedXRLabels = make (map [string ]string )
361+ }
362+ nestedXRLabels ["crossplane.io/composite" ] = compositeLabel
363+ nestedXR .SetLabels (nestedXRLabels )
364+ }
365+ }
366+ }
367+
327368func (p * DefaultDiffProcessor ) ProcessNestedXRs (
328369 ctx context.Context ,
329370 composedResources []cpd.Unstructured ,
@@ -382,48 +423,19 @@ func (p *DefaultDiffProcessor) ProcessNestedXRs(
382423
383424 // Find the matching existing nested XR in observed resources (if it exists)
384425 // Match by composition-resource-name annotation to find the correct existing resource
385- var existingNestedXR * un.Unstructured
386- compositionResourceName := nestedXR .GetAnnotations ()["crossplane.io/composition-resource-name" ]
387- if compositionResourceName != "" {
388- for _ , obs := range observedResources {
389- obsUnstructured := & un.Unstructured {Object : obs .UnstructuredContent ()}
390- obsCompResName := obsUnstructured .GetAnnotations ()["crossplane.io/composition-resource-name" ]
391-
392- // Match by composition-resource-name annotation and kind
393- if obsCompResName == compositionResourceName && obsUnstructured .GetKind () == nestedXR .GetKind () {
394- existingNestedXR = obsUnstructured
395- p .config .Logger .Debug ("Found existing nested XR in cluster" ,
396- "nestedXR" , nestedResourceID ,
397- "existingName" , existingNestedXR .GetName (),
398- "compositionResourceName" , compositionResourceName )
399- break
400- }
401- }
402- }
403-
404- // If we found an existing nested XR, preserve its identity (name, composite label)
405- // This ensures its managed resources can be matched correctly
426+ existingNestedXR := findExistingNestedXR (nestedXR , observedResources )
406427 if existingNestedXR != nil {
407- // Preserve the actual cluster name
408- nestedXR .SetName (existingNestedXR .GetName ())
409- nestedXR .SetGenerateName (existingNestedXR .GetGenerateName ())
410-
411- // Preserve the composite label so child resources get matched correctly
412- if labels := existingNestedXR .GetLabels (); labels != nil {
413- if compositeLabel , exists := labels ["crossplane.io/composite" ]; exists {
414- nestedXRLabels := nestedXR .GetLabels ()
415- if nestedXRLabels == nil {
416- nestedXRLabels = make (map [string ]string )
417- }
418- nestedXRLabels ["crossplane.io/composite" ] = compositeLabel
419- nestedXR .SetLabels (nestedXRLabels )
420-
421- p .config .Logger .Debug ("Preserved nested XR identity" ,
422- "nestedXR" , nestedResourceID ,
423- "preservedName" , nestedXR .GetName (),
424- "preservedCompositeLabel" , compositeLabel )
425- }
426- }
428+ p .config .Logger .Debug ("Found existing nested XR in cluster" ,
429+ "nestedXR" , nestedResourceID ,
430+ "existingName" , existingNestedXR .GetName (),
431+ "compositionResourceName" , nestedXR .GetAnnotations ()["crossplane.io/composition-resource-name" ])
432+
433+ // Preserve its identity (name, composite label) so its managed resources can be matched correctly
434+ preserveNestedXRIdentity (nestedXR , existingNestedXR )
435+
436+ p .config .Logger .Debug ("Preserved nested XR identity" ,
437+ "nestedXR" , nestedResourceID ,
438+ "preservedName" , nestedXR .GetName ())
427439 }
428440
429441 // Recursively process this nested XR
0 commit comments