policy/v2: SaaS-derived compat tests for nodeAttrs

Adds a data-driven test that loads testdata/nodeattrs_results/*.hujson
and diffs the captured SaaS-rendered netmaps against headscale's
compileNodeAttrs output. Each capture is one scenario the SaaS
control plane has rendered against the same policy headscale is asked
to compile -- the test enforces shape parity per node.

tailnet_state_caps.go enumerates the caps SaaS emits where headscale
has no equivalent concept yet (user-role admin/owner, tailnet lock,
services host, app connectors, internal magicsock and SSH tuning,
tailnet-state metadata) plus the always-on baseline (admin, ssh,
file-sharing) and the taildrive pair. stripUnmodelledTailnetStateCaps
filters both sides of cmp.Diff so the comparison focuses on the
policy-driven caps. PeerCapMap encodes which caps the Tailscale
client reads from the peer view (suggest-exit-node when exit routes
are approved, etc.) for use by the mapper.

testcapture switches to typed tailcfg/netmap/filtertype/apitype
values so schema drift between the capture tool and headscale
becomes a compile error rather than a silent test failure. Existing
compat suites (acl, grants, routes, ssh, issue_3212) move to the
typed shape.

The 53 SelfNode netmap captures and the 7 anonymizer-corrupted
suggest-charmander -> suggest-exit-node restorations in
routes_results / issue_3212 ride along.
This commit is contained in:
Kristoffer Dalby 2026-05-11 14:51:09 +00:00
parent 3f73ed5404
commit 078b9e308f
72 changed files with 463447 additions and 183 deletions

View file

@ -229,7 +229,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -257,7 +257,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],

View file

@ -229,7 +229,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -257,7 +257,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -1176,7 +1176,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -1204,7 +1204,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -2126,7 +2126,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -2154,7 +2154,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -3077,7 +3077,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -3105,7 +3105,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -4204,7 +4204,7 @@
"Tags": ["tag:exit", "tag:router"],
"PrimaryRoutes": ["172.16.0.0/24"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}, {
@ -5410,7 +5410,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -5438,7 +5438,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -6355,7 +6355,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -6383,7 +6383,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -7306,7 +7306,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -7334,7 +7334,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -8257,7 +8257,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -8285,7 +8285,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -9202,7 +9202,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -9230,7 +9230,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],
@ -10274,7 +10274,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -11535,7 +11535,7 @@
"Cap": 131,
"Tags": ["tag:exit"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "charmander",
"ComputedNameWithHost": "charmander"
}, {
@ -11563,7 +11563,7 @@
"Cap": 131,
"Tags": ["tag:exit", "tag:router"],
"Online": true,
"CapMap": {"suggest-charmander": null},
"CapMap": {"suggest-exit-node": null},
"ComputedName": "wartortle",
"ComputedNameWithHost": "wartortle"
}],