mirror of
https://github.com/juanfont/headscale.git
synced 2026-09-19 14:54:53 +09:00
policy,types: skip recompile when the user list is unchanged
SetUsers now also reports whether user-derived peer adjacency moved. Updates #3417
This commit is contained in:
@@ -647,3 +647,24 @@ func TestConcurrentPreAuthKeyRegistrationSameMachineKey(t *testing.T) {
|
||||
require.Equal(t, 1, s.ListNodes().Len(),
|
||||
"concurrent registrations of one machine key must yield a single node")
|
||||
}
|
||||
|
||||
// TestUpdatePolicyManagerUsersUnchangedKeepsSnapshot ensures re-sending the
|
||||
// same user list does not rebuild peer adjacency, while a real user change
|
||||
// does.
|
||||
func TestUpdatePolicyManagerUsersUnchangedKeepsSnapshot(t *testing.T) {
|
||||
_, s, _ := persistTestSetup(t)
|
||||
t.Cleanup(func() { _ = s.Close() })
|
||||
|
||||
require.NoError(t, s.UpdatePolicyManagerUsersForTest())
|
||||
|
||||
before := s.nodeStore.data.Load()
|
||||
|
||||
require.NoError(t, s.UpdatePolicyManagerUsersForTest())
|
||||
require.Same(t, before, s.nodeStore.data.Load(),
|
||||
"unchanged users must not rebuild the peer map")
|
||||
|
||||
_, _, err := s.CreateUser(types.User{Name: "second"})
|
||||
require.NoError(t, err)
|
||||
require.NotSame(t, before, s.nodeStore.data.Load(),
|
||||
"a user change must rebuild the peer map")
|
||||
}
|
||||
|
||||
@@ -2878,12 +2878,9 @@ func reauthChange(node types.NodeView, isRelogin, policyChanged bool) change.Cha
|
||||
}
|
||||
}
|
||||
|
||||
// updatePolicyManagerUsers updates the policy manager with current users.
|
||||
// Returns true if the policy changed and notifications should be sent.
|
||||
// TODO(kradalby): This is a temporary stepping stone, ultimately we should
|
||||
// have the list already available so it could go much quicker. Alternatively
|
||||
// the policy manager could have a remove or add list for users.
|
||||
// updatePolicyManagerUsers refreshes the policy manager with current user data.
|
||||
// updatePolicyManagerUsers pushes the current user list into the policy
|
||||
// manager, rebuilds peer adjacency when user identity changed, and returns
|
||||
// a PolicyChange when clients need a refresh.
|
||||
func (s *State) updatePolicyManagerUsers() (change.Change, error) {
|
||||
users, err := s.ListAllUsers()
|
||||
if err != nil {
|
||||
@@ -2892,13 +2889,20 @@ func (s *State) updatePolicyManagerUsers() (change.Change, error) {
|
||||
|
||||
log.Debug().Caller().Int("user.count", len(users)).Msg("policy manager user update initiated because user list modification detected")
|
||||
|
||||
changed, err := s.polMan.SetUsers(users)
|
||||
changed, peerMapChanged, err := s.polMan.SetUsers(users)
|
||||
if err != nil {
|
||||
return change.Change{}, fmt.Errorf("updating policy manager users: %w", err)
|
||||
}
|
||||
|
||||
log.Debug().Caller().Bool("policy.changed", changed).Msg("policy manager user update completed because SetUsers operation finished")
|
||||
|
||||
if peerMapChanged {
|
||||
// User-driven matcher state changed: rebuild candidate adjacency
|
||||
// so peer visibility reflects the new policy. Without this, the
|
||||
// cached peersByNode stays stale until the next node write.
|
||||
s.nodeStore.RebuildPeerMaps()
|
||||
}
|
||||
|
||||
if changed {
|
||||
return change.PolicyChange(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user