testcontrol: send updates for new DNS records or app capabilities
Two methods were recently added to the testcontrol.Server type: AddDNSRecords and SetGlobalAppCaps. These two methods should trigger netmap updates for all nodes connected to the Server instance, the way that other state-change methods do (see SetNodeCapMap, for example). This will also allow us to get rid of Server.ForceNetmapUpdate, which was a band-aid fix to force the netmap updates which should have been triggered by the aforementioned methods. Fixes tailscale/corp#37102 Signed-off-by: Harry Harpham <harry@tailscale.com>
This commit is contained in:
+2
-4
@@ -1194,10 +1194,8 @@ func TestListenService(t *testing.T) {
|
||||
tt.extraSetup(t, control)
|
||||
}
|
||||
|
||||
// Force netmap updates to avoid race conditions. The nodes need to
|
||||
// see our control updates before we can start the test.
|
||||
must.Do(control.ForceNetmapUpdate(ctx, serviceHost.lb.NodeKey()))
|
||||
must.Do(control.ForceNetmapUpdate(ctx, serviceClient.lb.NodeKey()))
|
||||
// Wait until both nodes have up-to-date netmaps before
|
||||
// proceeding with the test.
|
||||
netmapUpToDate := func(s *Server) bool {
|
||||
nm := s.lb.NetMap()
|
||||
return slices.ContainsFunc(nm.DNS.ExtraRecords, func(r tailcfg.DNSRecord) bool {
|
||||
|
||||
@@ -299,43 +299,6 @@ func (s *Server) addDebugMessage(nodeKeyDst key.NodePublic, msg any) bool {
|
||||
return sendUpdate(oldUpdatesCh, updateDebugInjection)
|
||||
}
|
||||
|
||||
// ForceNetmapUpdate waits for the node to get stuck in a map poll and then
|
||||
// sends the current netmap (which may result in a redundant netmap). The
|
||||
// intended use case is ensuring state changes propagate before running tests.
|
||||
//
|
||||
// This should only be called for nodes connected as streaming clients. Calling
|
||||
// this with a non-streaming node will result in non-deterministic behavior.
|
||||
//
|
||||
// This function cannot guarantee that the node has processed the issued update,
|
||||
// so tests should confirm processing by querying the node. By example:
|
||||
//
|
||||
// if err := s.ForceNetmapUpdate(node.Key()); err != nil {
|
||||
// // handle error
|
||||
// }
|
||||
// for !updatesPresent(node.NetMap()) {
|
||||
// time.Sleep(10 * time.Millisecond)
|
||||
// }
|
||||
func (s *Server) ForceNetmapUpdate(ctx context.Context, nodeKey key.NodePublic) error {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
if err := s.AwaitNodeInMapRequest(ctx, nodeKey); err != nil {
|
||||
return fmt.Errorf("waiting for node to poll: %w", err)
|
||||
}
|
||||
mr, err := s.MapResponse(&tailcfg.MapRequest{NodeKey: nodeKey})
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating map response: %w", err)
|
||||
}
|
||||
if s.addDebugMessage(nodeKey, mr) {
|
||||
return nil
|
||||
}
|
||||
// If we failed to send the map response, loop around and try again.
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the Node key of every node as expired
|
||||
func (s *Server) SetExpireAllNodes(expired bool) {
|
||||
s.mu.Lock()
|
||||
@@ -589,8 +552,9 @@ func (s *Server) SetNodeCapMap(nodeKey key.NodePublic, capMap tailcfg.NodeCapMap
|
||||
// ]
|
||||
func (s *Server) SetGlobalAppCaps(appCaps tailcfg.PeerCapMap) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.globalAppCaps = appCaps
|
||||
s.mu.Unlock()
|
||||
s.updateLocked("SetGlobalAppCaps", s.nodeIDsLocked(0))
|
||||
}
|
||||
|
||||
// AddDNSRecords adds records to the server's DNS config.
|
||||
@@ -601,6 +565,7 @@ func (s *Server) AddDNSRecords(records ...tailcfg.DNSRecord) {
|
||||
s.DNSConfig = new(tailcfg.DNSConfig)
|
||||
}
|
||||
s.DNSConfig.ExtraRecords = append(s.DNSConfig.ExtraRecords, records...)
|
||||
s.updateLocked("AddDNSRecords", s.nodeIDsLocked(0))
|
||||
}
|
||||
|
||||
// nodeIDsLocked returns the node IDs of all nodes in the server, except
|
||||
|
||||
Reference in New Issue
Block a user