@@ -1640,8 +1640,43 @@ func (r *ValkeyReconciler) upsertServiceAccount(ctx context.Context, valkey *hyp
16401640 }
16411641 if err := r .Create (ctx , sa ); err != nil {
16421642 if apierrors .IsAlreadyExists (err ) {
1643- if err := r .Update (ctx , sa ); err != nil {
1644- logger .Error (err , "failed to update service account" )
1643+ // Get existing resource
1644+ existingSA := & corev1.ServiceAccount {}
1645+ if err := r .Get (ctx , types.NamespacedName {Namespace : valkey .Namespace , Name : valkey .Name }, existingSA ); err != nil {
1646+ logger .Error (err , "failed to get existing service account" )
1647+ return err
1648+ }
1649+
1650+ // Check if changes are needed
1651+ desiredLabels := labels (valkey )
1652+ labelsChanged := ! labelsContains (existingSA .Labels , desiredLabels )
1653+ hasControllerRef := hasValkeyControllerReferences (existingSA .OwnerReferences , sa .OwnerReferences )
1654+
1655+ // Skip patch if no changes needed
1656+ if ! labelsChanged && hasControllerRef {
1657+ logger .Info ("service account already up to date, skipping patch" )
1658+ return nil
1659+ }
1660+
1661+ // Create patch only if changes are needed
1662+ patch := client .MergeFrom (existingSA .DeepCopy ())
1663+
1664+ // Update labels if changed
1665+ if labelsChanged {
1666+ existingSA .Labels = mergeLabels (existingSA .Labels , desiredLabels )
1667+ }
1668+
1669+ // Add controller reference if missing
1670+ if ! hasControllerRef {
1671+ if err := controllerutil .SetControllerReference (valkey , existingSA , r .Scheme ); err != nil {
1672+ logger .Error (err , "failed to set controller reference" )
1673+ return err
1674+ }
1675+ }
1676+
1677+ // Apply patch
1678+ if err := r .Patch (ctx , existingSA , patch ); err != nil {
1679+ logger .Error (err , "failed to patch service account" )
16451680 return err
16461681 }
16471682 } else {
@@ -1662,6 +1697,49 @@ func removePort(addr string) string {
16621697 return addr
16631698}
16641699
1700+ func labelsContains (existing , desired map [string ]string ) bool {
1701+ for k , v := range desired {
1702+ if existing [k ] != v {
1703+ return false
1704+ }
1705+ }
1706+ return true
1707+ }
1708+
1709+ func mergeLabels (existing , desired map [string ]string ) map [string ]string {
1710+ if existing == nil {
1711+ existing = make (map [string ]string )
1712+ }
1713+ for k , v := range desired {
1714+ existing [k ] = v
1715+ }
1716+ return existing
1717+ }
1718+
1719+ func hasValkeyControllerReferences (ownerRefs []metav1.OwnerReference , valkeyRefs []metav1.OwnerReference ) bool {
1720+ for _ , valkeyRef := range valkeyRefs {
1721+ if ! hasValkeyControllerReference (ownerRefs , valkeyRef ) {
1722+ return false
1723+ }
1724+ }
1725+ return true
1726+ }
1727+
1728+ // Compare the owner references of the Valkey resource with the provided reference
1729+ // to determine if the Valkey controller is already set as an owner.
1730+ // This method does not check for the controller field, as it is not set by default and may modified by other controllers.
1731+ func hasValkeyControllerReference (ownerRefs []metav1.OwnerReference , valkeyRef metav1.OwnerReference ) bool {
1732+ for _ , ref := range ownerRefs {
1733+ if ref .APIVersion == valkeyRef .APIVersion &&
1734+ ref .Kind == valkeyRef .Kind &&
1735+ ref .Name == valkeyRef .Name {
1736+ return true
1737+ }
1738+ }
1739+
1740+ return false
1741+ }
1742+
16651743func (r * ValkeyReconciler ) balanceNodes (ctx context.Context , valkey * hyperv1.Valkey ) error { // nolint: gocyclo
16661744 logger := log .FromContext (ctx )
16671745
0 commit comments