K8SPSMDB-1607: use order-insensitive comparison for user roles in updateRoles#2256
Open
racciari wants to merge 2 commits intopercona:mainfrom
Open
K8SPSMDB-1607: use order-insensitive comparison for user roles in updateRoles#2256racciari wants to merge 2 commits intopercona:mainfrom
racciari wants to merge 2 commits intopercona:mainfrom
Conversation
egegunes
previously approved these changes
Feb 26, 2026
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| mock := &mockMongoClientForRoles{} | ||
| err := updateRoles(context.Background(), mock, tt.user, tt.userInfo) |
Contributor
There was a problem hiding this comment.
you can consider using t.Context() here
MongoDB does not guarantee the order of roles returned by usersInfo command. The updateRoles function used reflect.DeepEqual to compare the desired roles from the CR spec with the roles returned by MongoDB. Since reflect.DeepEqual is order-sensitive, this caused an infinite reconciliation loop where the operator would repeatedly detect a "change" and call updateUser on every reconciliation cycle (~15s), even when the roles were semantically identical. This is the same class of bug that was fixed for custom roles comparison in rolesChanged() (K8SPSMDB-1146 / PR percona#1679), which correctly uses cmp.Equal with cmpopts.SortSlices. This commit applies the same fix to updateRoles() for user roles. Signed-off-by: Romain Acciari <romain.acciari+github@gmail.com>
8eb5d48 to
b675426
Compare
egegunes
approved these changes
Mar 2, 2026
gkech
approved these changes
Mar 4, 2026
Collaborator
commit: 6d23a02 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
updateRoles()function incustom_users.gousesreflect.DeepEqualto compare user roles from the CR spec with roles returned by MongoDB'susersInfocommand. Since MongoDB does not guarantee the order of roles in its response, this causes an infinite reconciliation loop where the operator repeatedly detects a "change" and callsupdateUseron every reconciliation cycle (~15 seconds), even when the roles are semantically identical.This is the same class of bug that was fixed for custom roles comparison in
rolesChanged()(K8SPSMDB-1146 / PR #1679), which correctly usescmp.Equalwithcmpopts.SortSlices. This PR applies the same fix toupdateRoles()for user roles.Root Cause
In
updateRoles()(line 360):reflect.DeepEqualcompares slices element-by-element in order. When MongoDB returns roles in a different order than specified in the CR, the comparison fails and triggers an unnecessaryupdateUsercall. MongoDB then returns the roles in yet another order, perpetuating the loop.Fix
Replace
reflect.DeepEqualwithcmp.Equalusingcmpopts.SortSlices, sorting by(DB, Role)— consistent with the approach already used inrolesChanged():Observed Impact
"User roles changed, updating them."every ~15 seconds for affected usersupdateUserMongoDB commands on every reconciliationTesting
Added
TestUpdateRoleswith 4 test cases:All existing tests pass.
Related
rolesChanged()