mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-30 18:24:06 +09:00
integration: reproduce HA primary flap to offline node via docker disconnect
Add a docker-network-disconnect primitive — `DisconnectFromNetwork` / `ReconnectToNetwork` on `TailscaleClient`, backed by `pool.Client.DisconnectNetwork` — so an integration test can faithfully simulate the cable-pull scenario the issue reporter observed in Proxmox. Iptables-based simulations leave the socket open at the container kernel and miss the bug. Use it in `TestHASubnetRouterFailoverDockerDisconnect` to assert the no-flap invariant: once primary has failed over from r1 to r2 and r2 also loses connectivity, primary must not switch back to the still-offline r1. The assertion fails on the current branch — the all-unhealthy fallback in `electPrimaryRoutes` flips primary to the lowest-NodeID candidate regardless of online state. Locking the failure in via TDD before designing the fix. Updates #3203
This commit is contained in:
1 parent
2d04fff605
commit
5228818a12
4 files changed
+250
No files matched your search
@@ -807,6 +807,21 @@ func (t *TailscaleInContainer) Down() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisconnectFromNetwork detaches the container from network at the
|
||||
// docker daemon level. The container's network interface for that
|
||||
// network disappears and any in-flight TCP connection is left
|
||||
// half-open at the peer — the same failure mode a real cable pull
|
||||
// produces, which iptables-based simulations cannot reproduce.
|
||||
func (t *TailscaleInContainer) DisconnectFromNetwork(network *dockertest.Network) error {
|
||||
return dockertestutil.DisconnectContainerFromNetwork(t.pool, network, t.hostname)
|
||||
}
|
||||
|
||||
// ReconnectToNetwork is the inverse of DisconnectFromNetwork: it
|
||||
// re-attaches the container to network so traffic can flow again.
|
||||
func (t *TailscaleInContainer) ReconnectToNetwork(network *dockertest.Network) error {
|
||||
return dockertestutil.ReconnectContainerToNetwork(t.pool, network, t.hostname)
|
||||
}
|
||||
|
||||
// IPs returns the netip.Addr of the Tailscale instance.
|
||||
func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) {
|
||||
if len(t.ips) != 0 {
|
||||
|
||||
Reference in new issue
Block a user