From 5083d77731f0863635c1747f259cc116d9cf8819 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 30 Oct 2026 16:01:54 +0000 Subject: [PATCH] mapper: leave online state off a node's own entry As SaaS. Clients take their own state from the map poll. Updates #3626 --- hscontrol/mapper/builder.go | 4 ++-- hscontrol/servertest/lifecycle_test.go | 4 ++-- hscontrol/servertest/mapstream_compat_test.go | 3 --- integration/helpers.go | 2 -- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/hscontrol/mapper/builder.go b/hscontrol/mapper/builder.go index 4387a92f4..12487ee6e 100644 --- a/hscontrol/mapper/builder.go +++ b/hscontrol/mapper/builder.go @@ -115,8 +115,8 @@ func (b *MapResponseBuilder) WithSelfNode() *MapResponseBuilder { tailnode.MachineAuthorized = true tailnode.Expired = false - // As on Tailscale SaaS. A client knows its own version. - tailnode.Cap = 0 + // As on Tailscale SaaS. A client knows its own version and connection. + tailnode.Cap, tailnode.Online, tailnode.LastSeen = 0, nil, nil tailnode.Hostinfo = types.SelfHostinfo(tailnode.Hostinfo) diff --git a/hscontrol/servertest/lifecycle_test.go b/hscontrol/servertest/lifecycle_test.go index 968587ff5..260da384e 100644 --- a/hscontrol/servertest/lifecycle_test.go +++ b/hscontrol/servertest/lifecycle_test.go @@ -178,7 +178,8 @@ func TestNodeExpiryPreservesControlConnection(t *testing.T) { assert.Equal(c, epoch, current.SessionEpoch()) assert.True(c, h.Server.App.MapBatcher().IsConnected(id)) assert.True(c, client.Netmap().SelfNode.KeyExpiry().Before(time.Now())) - assert.False(c, client.Netmap().SelfNode.Online().Get()) + assert.False(c, client.Netmap().SelfNode.Online().Valid()) + assert.False(c, client.Netmap().SelfNode.LastSeen().Valid()) // Peers still see the connected node online, as on Tailscale SaaS. peer, found := observer.PeerByName(client.Name) @@ -222,7 +223,6 @@ func TestNodeExpiryPreservesControlConnection(t *testing.T) { assert.Equal(c, nodeKey, current.NodeKey()) assert.Equal(c, 1, current.ActiveSessions()) assert.True(c, client.Netmap().SelfNode.KeyExpiry().IsZero()) - assert.True(c, client.Netmap().SelfNode.Online().Get()) peer, found := observer.PeerByName(client.Name) if assert.True(c, found) { diff --git a/hscontrol/servertest/mapstream_compat_test.go b/hscontrol/servertest/mapstream_compat_test.go index b026b3573..e593300e7 100644 --- a/hscontrol/servertest/mapstream_compat_test.go +++ b/hscontrol/servertest/mapstream_compat_test.go @@ -60,8 +60,6 @@ var mapStreamSkipReasons = map[string]string{ "map-delivery/S3.5-remove/db1/frames": policyResponseToEveryNode, "map-delivery/S3.5-restore/db1/frames": policyResponseToEveryNode, - "map-delivery/S2.0/own-entry/Online": ownOnlineSent, - "map-delivery/S2.5/laptop/endpoints-gap-bystander": restartEndpointsKept, "map-delivery/S2.5/laptop/endpoints-gap-svc": restartEndpointsKept, @@ -101,7 +99,6 @@ var mapStreamSkipReasons = map[string]string{ const ( policyResponseToEveryNode = "POLICY_RESPONSE_TO_EVERY_NODE: headscale sends every connected node a policy response when the policy, a node's tags or approved routes, or the set of nodes change; SaaS sends only the nodes whose peers or filter change" restartEndpointsKept = "RESTART_ENDPOINTS_KEPT: headscale keeps a restarted node's last endpoints at its peers until it reports new ones; SaaS sends peers the node without endpoints until then" - ownOnlineSent = "OWN_ONLINE_SENT: headscale sets Online on a node's own entry; SaaS only on peers" ) // mapStreamNotCompared lists, by key prefix, checks left out: SaaS's answer diff --git a/integration/helpers.go b/integration/helpers.go index 4e1e6e640..034dd13cc 100644 --- a/integration/helpers.go +++ b/integration/helpers.go @@ -806,8 +806,6 @@ func assertValidNetmap(t *testing.T, client TailscaleClient) { assert.NotEmptyf(c, netmap.SelfNode.AllowedIPs(), "%q does not have any allowed IPs", client.Hostname()) assert.NotEmptyf(c, netmap.SelfNode.Addresses(), "%q does not have any addresses", client.Hostname()) - assert.Truef(c, netmap.SelfNode.Online().Get(), "%q is not online", client.Hostname()) - assert.Falsef(c, netmap.SelfNode.Key().IsZero(), "%q does not have a valid NodeKey", client.Hostname()) assert.Falsef(c, netmap.SelfNode.DiscoKey().IsZero(), "%q does not have a valid DiscoKey", client.Hostname())