state: refresh policy nodes inside the peer map build

One peer build per tag/user/IP/route write; callers detect policy moves
via NodesGeneration. Per-node caches only store results for the node
pm holds, so a mapper reading mid-build cannot pin a stale filter.
This commit is contained in:
Kristoffer Dalby
2026-09-25 17:36:26 +00:00
parent 311d9323e0
commit 21f6e46fb8
17 changed files with 1085 additions and 148 deletions
+4 -2
View File
@@ -91,16 +91,18 @@ func registerAuth(api huma.API, b Backend) {
util.RegisterMethodCLI,
)
if err != nil {
b.Change(nodeChange)
return nil, mapError("registering node", err)
}
routeChange, err := b.State.AutoApproveRoutes(node)
b.Change(nodeChange, routeChange)
if err != nil {
return nil, huma.Error500InternalServerError("auto approving routes", err)
}
b.Change(nodeChange, routeChange)
out := &authRegisterOutput{}
out.Body.Node = nodeFromView(node)
+19 -14
View File
@@ -309,12 +309,12 @@ func registerNodeWriteOps(api huma.API, b Backend) {
switch {
case disableExpiry:
node, nodeChange, expErr := b.State.SetNodeExpiry(nodeID, nil)
b.Change(nodeChange)
if expErr != nil {
return nil, mapError("expiring node", expErr)
}
b.Change(nodeChange)
out := &nodeOutput{}
out.Body.Node = nodeFromView(node)
@@ -324,12 +324,12 @@ func registerNodeWriteOps(api huma.API, b Backend) {
}
node, nodeChange, err := b.State.SetNodeExpiry(nodeID, &expiry)
b.Change(nodeChange)
if err != nil {
return nil, mapError("expiring node", err)
}
b.Change(nodeChange)
out := &nodeOutput{}
out.Body.Node = nodeFromView(node)
@@ -350,12 +350,12 @@ func registerNodeWriteOps(api huma.API, b Backend) {
}
node, nodeChange, err := b.State.RenameNode(nodeID, in.NewName)
b.Change(nodeChange)
if err != nil {
return nil, mapError("renaming node", err)
}
b.Change(nodeChange)
out := &nodeOutput{}
out.Body.Node = nodeFromView(node)
@@ -396,12 +396,12 @@ func registerNodeWriteOps(api huma.API, b Backend) {
}
node, nodeChange, err := b.State.SetNodeTags(nodeID, in.Body.Tags)
b.Change(nodeChange)
if err != nil {
return nil, huma.Error400BadRequest("setting tags", err)
}
b.Change(nodeChange)
out := &nodeOutput{}
out.Body.Node = nodeFromView(node)
@@ -444,12 +444,12 @@ func registerNodeAdminOps(api huma.API, b Backend) {
newApproved = slices.Compact(newApproved)
node, nodeChange, err := b.State.SetApprovedRoutes(nodeID, newApproved)
b.Change(nodeChange)
if err != nil {
return nil, mapError("setting approved routes", err)
}
b.Change(nodeChange)
out := &nodeOutput{}
out.Body.Node = nodeFromView(node)
// SubnetRoutes here excludes exit routes, unlike the list handler.
@@ -485,17 +485,20 @@ func registerNodeAdminOps(api huma.API, b Backend) {
util.RegisterMethodCLI,
)
if err != nil {
b.Change(nodeChange)
return nil, mapError("registering node", err)
}
routeChange, err := b.State.AutoApproveRoutes(node)
if err != nil {
return nil, huma.Error500InternalServerError("auto approving routes", err)
}
// Empty changes are ignored by the change sink.
b.Change(nodeChange, routeChange)
if err != nil {
return nil, huma.Error500InternalServerError("auto approving routes", err)
}
out := &nodeOutput{}
out.Body.Node = nodeFromView(node)
@@ -514,7 +517,9 @@ func registerNodeAdminOps(api huma.API, b Backend) {
return nil, huma.Error400BadRequest("backfilling node IPs", errBackfillNotConfirmed)
}
changes, err := b.State.BackfillNodeIPs()
changes, cs, err := b.State.BackfillNodeIPs()
b.Change(cs...)
if err != nil {
return nil, huma.Error500InternalServerError("backfilling node IPs", err)
}
+2 -4
View File
@@ -143,14 +143,12 @@ func registerPolicy(api huma.API, b Backend) {
// Reload even when content is unchanged: routes manually disabled before
// may now qualify for auto-approval, so they must be re-evaluated.
cs, err := b.State.ReloadPolicy()
b.Change(cs...)
if err != nil {
return nil, huma.Error500InternalServerError("reloading policy", err)
}
if len(cs) > 0 {
b.Change(cs...)
}
out := &setPolicyOutput{}
out.Body.Policy = updated.Data
out.Body.UpdatedAt = updated.UpdatedAt