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)
|
tt.extraSetup(t, control)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force netmap updates to avoid race conditions. The nodes need to
|
// Wait until both nodes have up-to-date netmaps before
|
||||||
// see our control updates before we can start the test.
|
// proceeding with the test.
|
||||||
must.Do(control.ForceNetmapUpdate(ctx, serviceHost.lb.NodeKey()))
|
|
||||||
must.Do(control.ForceNetmapUpdate(ctx, serviceClient.lb.NodeKey()))
|
|
||||||
netmapUpToDate := func(s *Server) bool {
|
netmapUpToDate := func(s *Server) bool {
|
||||||
nm := s.lb.NetMap()
|
nm := s.lb.NetMap()
|
||||||
return slices.ContainsFunc(nm.DNS.ExtraRecords, func(r tailcfg.DNSRecord) bool {
|
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)
|
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
|
// Mark the Node key of every node as expired
|
||||||
func (s *Server) SetExpireAllNodes(expired bool) {
|
func (s *Server) SetExpireAllNodes(expired bool) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
@@ -589,8 +552,9 @@ func (s *Server) SetNodeCapMap(nodeKey key.NodePublic, capMap tailcfg.NodeCapMap
|
|||||||
// ]
|
// ]
|
||||||
func (s *Server) SetGlobalAppCaps(appCaps tailcfg.PeerCapMap) {
|
func (s *Server) SetGlobalAppCaps(appCaps tailcfg.PeerCapMap) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
s.globalAppCaps = appCaps
|
s.globalAppCaps = appCaps
|
||||||
s.mu.Unlock()
|
s.updateLocked("SetGlobalAppCaps", s.nodeIDsLocked(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddDNSRecords adds records to the server's DNS config.
|
// 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 = new(tailcfg.DNSConfig)
|
||||||
}
|
}
|
||||||
s.DNSConfig.ExtraRecords = append(s.DNSConfig.ExtraRecords, records...)
|
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
|
// nodeIDsLocked returns the node IDs of all nodes in the server, except
|
||||||
|
|||||||
Reference in New Issue
Block a user