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
+2 -4
View File
@@ -134,14 +134,12 @@ func registerACL(api huma.API, b Backend) {
}
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...)
}
return streamPolicy([]byte(updated.Data), aclContentType(in.Accept)), nil
})
}
+8 -8
View File
@@ -232,12 +232,12 @@ func registerDevices(api huma.API, b Backend) {
}
_, nodeChange, err := b.State.RenameNode(node.ID(), in.Body.Name)
b.Change(nodeChange)
if err != nil {
return nil, mapError("renaming device", err)
}
b.Change(nodeChange)
return &emptyOutput{}, nil
})
@@ -278,12 +278,12 @@ func registerDevices(api huma.API, b Backend) {
}
_, nodeChange, err := b.State.SetNodeTags(node.ID(), in.Body.Tags)
b.Change(nodeChange)
if err != nil {
return nil, mapError("setting device tags", err)
}
b.Change(nodeChange)
return &emptyOutput{}, nil
})
@@ -311,12 +311,12 @@ func registerDevices(api huma.API, b Backend) {
}
_, nodeChange, err := b.State.SetNodeExpiry(node.ID(), nil)
b.Change(nodeChange)
if err != nil {
return nil, mapError("setting device key expiry", err)
}
b.Change(nodeChange)
return &emptyOutput{}, nil
})
@@ -341,12 +341,12 @@ func registerDevices(api huma.API, b Backend) {
}
updated, nodeChange, err := b.State.SetApprovedRoutes(node.ID(), approved)
b.Change(nodeChange)
if err != nil {
return nil, mapError("setting device routes", err)
}
b.Change(nodeChange)
return &deviceRoutesOutput{Body: routesFromView(updated)}, nil
})