mirror of
https://github.com/juanfont/headscale.git
synced 2026-04-22 16:48:40 +02:00
mapper: move tail node conversion to node type (#2950)
This commit is contained in:
@@ -76,8 +76,9 @@ func (b *MapResponseBuilder) WithSelfNode() *MapResponseBuilder {
|
||||
}
|
||||
|
||||
_, matchers := b.mapper.state.Filter()
|
||||
tailnode, err := tailNode(
|
||||
nv, b.capVer,
|
||||
|
||||
tailnode, err := nv.TailNode(
|
||||
b.capVer,
|
||||
func(id types.NodeID) []netip.Prefix {
|
||||
return policy.ReduceRoutes(nv, b.mapper.state.GetNodePrimaryRoutes(id), matchers)
|
||||
},
|
||||
@@ -251,7 +252,7 @@ func (b *MapResponseBuilder) buildTailPeers(peers views.Slice[types.NodeView]) (
|
||||
changedViews = peers
|
||||
}
|
||||
|
||||
tailPeers, err := tailNodes(
|
||||
tailPeers, err := types.TailNodes(
|
||||
changedViews, b.capVer,
|
||||
func(id types.NodeID) []netip.Prefix {
|
||||
return policy.ReduceRoutes(node, b.mapper.state.GetNodePrimaryRoutes(id), matchers)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
@@ -259,11 +258,6 @@ func writeDebugMapResponse(
|
||||
}
|
||||
}
|
||||
|
||||
// routeFilterFunc is a function that takes a node ID and returns a list of
|
||||
// netip.Prefixes that are allowed for that node. It is used to filter routes
|
||||
// from the primary route manager to the node.
|
||||
type routeFilterFunc func(id types.NodeID) []netip.Prefix
|
||||
|
||||
func (m *mapper) debugMapResponses() (map[types.NodeID][]tailcfg.MapResponse, error) {
|
||||
if debugDumpMapResponsePath == "" {
|
||||
return nil, nil
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
package mapper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/views"
|
||||
)
|
||||
|
||||
func tailNodes(
|
||||
nodes views.Slice[types.NodeView],
|
||||
capVer tailcfg.CapabilityVersion,
|
||||
primaryRouteFunc routeFilterFunc,
|
||||
cfg *types.Config,
|
||||
) ([]*tailcfg.Node, error) {
|
||||
tNodes := make([]*tailcfg.Node, 0, nodes.Len())
|
||||
|
||||
for _, node := range nodes.All() {
|
||||
tNode, err := tailNode(
|
||||
node,
|
||||
capVer,
|
||||
primaryRouteFunc,
|
||||
cfg,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tNodes = append(tNodes, tNode)
|
||||
}
|
||||
|
||||
return tNodes, nil
|
||||
}
|
||||
|
||||
// tailNode converts a Node into a Tailscale Node.
|
||||
func tailNode(
|
||||
node types.NodeView,
|
||||
capVer tailcfg.CapabilityVersion,
|
||||
primaryRouteFunc routeFilterFunc,
|
||||
cfg *types.Config,
|
||||
) (*tailcfg.Node, error) {
|
||||
addrs := node.Prefixes()
|
||||
|
||||
var derp int
|
||||
|
||||
// TODO(kradalby): legacyDERP was removed in tailscale/tailscale@2fc4455e6dd9ab7f879d4e2f7cffc2be81f14077
|
||||
// and should be removed after 111 is the minimum capver.
|
||||
var legacyDERP string
|
||||
if node.Hostinfo().Valid() && node.Hostinfo().NetInfo().Valid() {
|
||||
legacyDERP = fmt.Sprintf("127.3.3.40:%d", node.Hostinfo().NetInfo().PreferredDERP())
|
||||
derp = node.Hostinfo().NetInfo().PreferredDERP()
|
||||
} else {
|
||||
legacyDERP = "127.3.3.40:0" // Zero means disconnected or unknown.
|
||||
}
|
||||
|
||||
var keyExpiry time.Time
|
||||
if node.Expiry().Valid() {
|
||||
keyExpiry = node.Expiry().Get()
|
||||
} else {
|
||||
keyExpiry = time.Time{}
|
||||
}
|
||||
|
||||
hostname, err := node.GetFQDN(cfg.BaseDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
routes := primaryRouteFunc(node.ID())
|
||||
allowed := append(addrs, routes...)
|
||||
allowed = append(allowed, node.ExitRoutes()...)
|
||||
tsaddr.SortPrefixes(allowed)
|
||||
|
||||
tNode := tailcfg.Node{
|
||||
ID: tailcfg.NodeID(node.ID()), // this is the actual ID
|
||||
StableID: node.ID().StableID(),
|
||||
Name: hostname,
|
||||
Cap: capVer,
|
||||
|
||||
User: node.TailscaleUserID(),
|
||||
|
||||
Key: node.NodeKey(),
|
||||
KeyExpiry: keyExpiry.UTC(),
|
||||
|
||||
Machine: node.MachineKey(),
|
||||
DiscoKey: node.DiscoKey(),
|
||||
Addresses: addrs,
|
||||
PrimaryRoutes: routes,
|
||||
AllowedIPs: allowed,
|
||||
Endpoints: node.Endpoints().AsSlice(),
|
||||
HomeDERP: derp,
|
||||
LegacyDERPString: legacyDERP,
|
||||
Hostinfo: node.Hostinfo(),
|
||||
Created: node.CreatedAt().UTC(),
|
||||
|
||||
Online: node.IsOnline().Clone(),
|
||||
|
||||
Tags: node.Tags().AsSlice(),
|
||||
|
||||
MachineAuthorized: !node.IsExpired(),
|
||||
Expired: node.IsExpired(),
|
||||
}
|
||||
|
||||
tNode.CapMap = tailcfg.NodeCapMap{
|
||||
tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{},
|
||||
tailcfg.CapabilityAdmin: []tailcfg.RawMessage{},
|
||||
tailcfg.CapabilitySSH: []tailcfg.RawMessage{},
|
||||
}
|
||||
|
||||
if cfg.RandomizeClientPort {
|
||||
tNode.CapMap[tailcfg.NodeAttrRandomizeClientPort] = []tailcfg.RawMessage{}
|
||||
}
|
||||
|
||||
// Set LastSeen only for offline nodes to avoid confusing Tailscale clients
|
||||
// during rapid reconnection cycles. Online nodes should not have LastSeen set
|
||||
// as this can make clients interpret them as "not online" despite Online=true.
|
||||
if node.LastSeen().Valid() && node.IsOnline().Valid() && !node.IsOnline().Get() {
|
||||
lastSeen := node.LastSeen().Get()
|
||||
tNode.LastSeen = &lastSeen
|
||||
}
|
||||
|
||||
return &tNode, nil
|
||||
}
|
||||
@@ -211,8 +211,7 @@ func TestTailNode(t *testing.T) {
|
||||
// This is a hack to avoid having a second node to test the primary route.
|
||||
// This should be baked into the test case proper if it is extended in the future.
|
||||
_ = primary.SetRoutes(2, netip.MustParsePrefix("192.168.0.0/24"))
|
||||
got, err := tailNode(
|
||||
tt.node.View(),
|
||||
got, err := tt.node.View().TailNode(
|
||||
0,
|
||||
func(id types.NodeID) []netip.Prefix {
|
||||
return primary.PrimaryRoutes(id)
|
||||
@@ -221,13 +220,13 @@ func TestTailNode(t *testing.T) {
|
||||
)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("tailNode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
t.Errorf("TailNode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(tt.want, got, cmpopts.EquateEmpty()); diff != "" {
|
||||
t.Errorf("tailNode() unexpected result (-want +got):\n%s", diff)
|
||||
t.Errorf("TailNode() unexpected result (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -268,8 +267,7 @@ func TestNodeExpiry(t *testing.T) {
|
||||
Expiry: tt.exp,
|
||||
}
|
||||
|
||||
tn, err := tailNode(
|
||||
node.View(),
|
||||
tn, err := node.View().TailNode(
|
||||
0,
|
||||
func(id types.NodeID) []netip.Prefix {
|
||||
return []netip.Prefix{}
|
||||
|
||||
Reference in New Issue
Block a user