Skip to content

Commit 8f32c4b

Browse files
authored
Merge pull request #308 from hyperspike/serviceaccount
Serviceaccount upserting
2 parents 9a3434f + e16cee1 commit 8f32c4b

1 file changed

Lines changed: 80 additions & 2 deletions

File tree

internal/controller/valkey_controller.go

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
16651743
func (r *ValkeyReconciler) balanceNodes(ctx context.Context, valkey *hyperv1.Valkey) error { // nolint: gocyclo
16661744
logger := log.FromContext(ctx)
16671745

0 commit comments

Comments
 (0)