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:
parent
3f73ed5404
commit
078b9e308f
72 changed files with 463447 additions and 183 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// This file implements a data-driven test runner for ACL compatibility tests.
|
||||
// It loads HuJSON golden files from testdata/acl_results/acl-*.hujson and
|
||||
// compares headscale's ACL engine output against the expected packet filter
|
||||
// rules captured from Tailscale SaaS by the tscap tool.
|
||||
// rules captured from a Tailscale-hosted control plane by an external capture tool.
|
||||
//
|
||||
// Each file is a testcapture.Capture containing:
|
||||
// - The full policy that was POSTed to the Tailscale SaaS API
|
||||
|
|
@ -40,8 +40,8 @@ func ptrAddr(s string) *netip.Addr {
|
|||
}
|
||||
|
||||
// setupACLCompatUsers returns the 3 test users for ACL compatibility tests.
|
||||
// Names and emails match the anonymized identifiers tscap writes into the
|
||||
// capture files (see github.com/kradalby/tscap/anonymize): users get
|
||||
// Names and emails match the anonymized identifiers the capture tool writes into the
|
||||
// capture files users get
|
||||
// norse-god names and nodes get original-151 pokémon names.
|
||||
func setupACLCompatUsers() types.Users {
|
||||
return types.Users{
|
||||
|
|
@ -52,7 +52,7 @@ func setupACLCompatUsers() types.Users {
|
|||
}
|
||||
|
||||
// setupACLCompatNodes returns the 8 test nodes for ACL compatibility tests.
|
||||
// Node GivenNames match tscap's anonymized pokémon naming.
|
||||
// Node GivenNames match the anonymized pokémon naming.
|
||||
func setupACLCompatNodes(users types.Users) types.Nodes {
|
||||
return types.Nodes{
|
||||
{
|
||||
|
|
@ -291,7 +291,7 @@ func TestACLCompat(t *testing.T) {
|
|||
}
|
||||
|
||||
// Build nodes per-scenario from this file's topology.
|
||||
// tscap uses clean-slate mode, so each scenario has
|
||||
// the capture tool uses clean-slate mode, so each scenario has
|
||||
// different node IPs; using a shared topology would
|
||||
// cause IP mismatches in filter rule comparisons.
|
||||
users, nodes := buildACLUsersAndNodes(t, tf)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue