types/node, mapper, policy/v2: assemble self CapMap inside TailNode
types.NodeView.TailNode takes a selfPolicyCaps tailcfg.NodeCapMap parameter and merges it into the baseline. The mapper's WithSelfNode hands it the policy result via state.NodeCapMap; peer-path callers pass nil because peer-side CapMap is set downstream via policyv2.PeerCapMap. The nodeAttrs compat test now diffs the full TailNode self-view output against captured SaaS netmaps. Before this change the test compared compileNodeAttrs alone -- the policy-only output -- and needed a strip list to compensate for the missing baseline. With TailNode on the diff path, baseline emission is exercised end-to-end by every capture; a regression in TailNode breaks the suite. unmodelledTailnetStateCaps drops cap/ssh and cap/file-sharing now that both sides emit them identically. The file header is rewritten to read as 'caps SaaS emits where headscale has no equivalent yet' rather than the more confusing 'shape divergence' framing.
This commit is contained in:
parent
b3f795f0b4
commit
5ebc53c29e
5 changed files with 77 additions and 64 deletions
|
|
@ -1,7 +1,6 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"net/netip"
|
||||
"slices"
|
||||
"sort"
|
||||
|
|
@ -86,20 +85,14 @@ func (b *MapResponseBuilder) WithSelfNode() *MapResponseBuilder {
|
|||
|
||||
return slices.Concat(primaries, nv.ExitRoutes())
|
||||
},
|
||||
b.mapper.cfg)
|
||||
b.mapper.cfg,
|
||||
b.mapper.state.NodeCapMap(nv.ID()),
|
||||
)
|
||||
if err != nil {
|
||||
b.addError(err)
|
||||
return b
|
||||
}
|
||||
|
||||
if policyCaps := b.mapper.state.NodeCapMap(nv.ID()); len(policyCaps) > 0 {
|
||||
if tailnode.CapMap == nil {
|
||||
tailnode.CapMap = make(tailcfg.NodeCapMap, len(policyCaps))
|
||||
}
|
||||
|
||||
maps.Copy(tailnode.CapMap, policyCaps)
|
||||
}
|
||||
|
||||
b.resp.Node = tailnode
|
||||
|
||||
return b
|
||||
|
|
@ -276,7 +269,7 @@ func (b *MapResponseBuilder) buildTailPeers(peers views.Slice[types.NodeView]) (
|
|||
for _, peer := range changedViews.All() {
|
||||
tn, err := peer.TailNode(b.capVer, func(_ types.NodeID) []netip.Prefix {
|
||||
return b.mapper.state.RoutesForPeer(node, peer, matchers)
|
||||
}, b.mapper.cfg)
|
||||
}, b.mapper.cfg, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import (
|
|||
)
|
||||
|
||||
func TestTailNode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
mustNK := func(str string) key.NodePublic {
|
||||
var k key.NodePublic
|
||||
|
||||
|
|
@ -51,7 +53,6 @@ func TestTailNode(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
node *types.Node
|
||||
pol []byte
|
||||
dnsConfig *tailcfg.DNSConfig
|
||||
baseDomain string
|
||||
want *tailcfg.Node
|
||||
|
|
@ -208,6 +209,8 @@ func TestTailNode(t *testing.T) {
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := &types.Config{
|
||||
BaseDomain: tt.baseDomain,
|
||||
TailcfgDNSConfig: tt.dnsConfig,
|
||||
|
|
@ -233,6 +236,7 @@ func TestTailNode(t *testing.T) {
|
|||
return slices.Concat(primaries[id], nv.ExitRoutes())
|
||||
},
|
||||
cfg,
|
||||
nil,
|
||||
)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
|
|
@ -289,6 +293,7 @@ func TestNodeExpiry(t *testing.T) {
|
|||
return []netip.Prefix{}
|
||||
},
|
||||
&types.Config{Taildrop: types.TaildropConfig{Enabled: true}},
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("nodeExpiry() error = %v", err)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue