mirror of
https://github.com/tailscale/tailscale.git
synced 2026-05-05 04:06:35 +02:00
ipn, ipn/ipnlocal: add Notify.SelfChange
Add a new bus signal that lets reactive consumers (containerboot, kube agents, sniproxy, tsconsensus, etc.) react to self-node updates without having to subscribe to the full netmap. Today those consumers either watch Notify.NetMap (which on large tailnets is expensive to encode and ship per watcher) or poll. SelfChange is a cheap, narrow alternative: addresses, name, key expiry, capabilities, etc. Consumers that need additional state can react to SelfChange and then fetch the relevant bits on demand via existing LocalClient methods. Producer-side, every netmap-bearing setControlClientStatus call now also publishes SelfChange. Future changes will migrate individual in-tree consumers off Notify.NetMap to this signal, and eventually gate the legacy NetMap emission to platforms whose host GUIs still require it. Updates #12542 Change-Id: I4441650b0e085d663eb6bf26a03748b7d961ca49 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
9f343fdc0c
commit
a6c5d23742
@ -118,6 +118,17 @@ type Notify struct {
|
||||
Prefs *PrefsView // if non-nil && Valid, the new or current preferences
|
||||
NetMap *netmap.NetworkMap // if non-nil, the new or current netmap
|
||||
|
||||
// SelfChange, if non-nil, indicates that this node's own [tailcfg.Node]
|
||||
// has changed: addresses, name, key expiry, capabilities, etc. It carries
|
||||
// the new self node so reactive consumers (containerboot, kube agents,
|
||||
// sniproxy, etc.) can read the current self state without watching the
|
||||
// full netmap.
|
||||
//
|
||||
// Consumers that need additional state (peers, DNS config, packet
|
||||
// filter) should react to SelfChange by fetching the relevant bits on
|
||||
// demand via [LocalClient].
|
||||
SelfChange *tailcfg.Node `json:",omitzero"`
|
||||
|
||||
// PeerChanges, if non-nil, is a list of [tailcfg.PeerChange] that have occurred since the last
|
||||
// full netmap update. This is sent in lieu of a full NetMap when [NotifyPeerChanges] is set in
|
||||
// the session's mask and a netmap update is derived from an incremental MapResponse.
|
||||
@ -196,6 +207,9 @@ func (n Notify) String() string {
|
||||
if n.NetMap != nil {
|
||||
sb.WriteString("NetMap{...} ")
|
||||
}
|
||||
if n.SelfChange != nil {
|
||||
fmt.Fprintf(&sb, "SelfChange(%v) ", n.SelfChange.StableID)
|
||||
}
|
||||
if n.PeerChanges != nil {
|
||||
fmt.Fprintf(&sb, "PeerChanges(%d) ", len(n.PeerChanges))
|
||||
}
|
||||
|
||||
@ -205,6 +205,7 @@ func isNotableNotify(n *ipn.Notify) bool {
|
||||
n.Prefs != nil ||
|
||||
n.ErrMessage != nil ||
|
||||
n.LoginFinished != nil ||
|
||||
n.SelfChange != nil ||
|
||||
!n.DriveShares.IsNil() ||
|
||||
n.Health != nil ||
|
||||
len(n.IncomingFiles) > 0 ||
|
||||
|
||||
@ -32,6 +32,7 @@ func TestIsNotableNotify(t *testing.T) {
|
||||
{"netmap", &ipn.Notify{NetMap: new(netmap.NetworkMap)}, false},
|
||||
{"peerchanges", &ipn.Notify{PeerChanges: []*tailcfg.PeerChange{{}}}, false},
|
||||
{"engine", &ipn.Notify{Engine: new(ipn.EngineStatus)}, false},
|
||||
{"selfchange", &ipn.Notify{SelfChange: &tailcfg.Node{}}, true},
|
||||
}
|
||||
|
||||
// Then for all other fields, assume they're notable.
|
||||
@ -41,7 +42,7 @@ func TestIsNotableNotify(t *testing.T) {
|
||||
for sf := range rt.Fields() {
|
||||
n := &ipn.Notify{}
|
||||
switch sf.Name {
|
||||
case "_", "NetMap", "PeerChanges", "Engine", "Version":
|
||||
case "_", "NetMap", "PeerChanges", "SelfChange", "Engine", "Version":
|
||||
// Already covered above or not applicable.
|
||||
continue
|
||||
case "DriveShares":
|
||||
|
||||
@ -1897,7 +1897,15 @@ func (b *LocalBackend) setControlClientStatusLocked(c controlclient.Client, st c
|
||||
// Update the DERP map in the health package, which uses it for health notifications
|
||||
b.health.SetDERPMap(st.NetMap.DERPMap)
|
||||
|
||||
b.sendLocked(ipn.Notify{NetMap: st.NetMap})
|
||||
// Notify watchers that the self node may have changed. Reactive
|
||||
// consumers (containerboot, kube agents, sniproxy, etc.) listen on
|
||||
// this signal and re-fetch peers/DNS via the LocalAPI if they need
|
||||
// more than self info.
|
||||
var selfChange *tailcfg.Node
|
||||
if st.NetMap.SelfNode.Valid() {
|
||||
selfChange = st.NetMap.SelfNode.AsStruct()
|
||||
}
|
||||
b.sendLocked(ipn.Notify{NetMap: st.NetMap, SelfChange: selfChange})
|
||||
|
||||
// The error here is unimportant as is the result. This will recalculate the suggested exit node
|
||||
// cache the value and push any changes to the IPN bus.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user