Resolve the per-certname routes to the node's owning backend
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful

The paths keyed on one certname took the pass-through, so a node both
backends hold answered from whichever was configured first while /facts
answered from whichever held its newer report.

- add a route claiming /pdb/query/v4/{nodes,factsets,catalogs}/<certname>
- order the backends for it by the freshness map the /facts merge uses
- try the remaining backends after the owner, replaying upstream's 404 when none holds the certname
- assert ownership, the upstream 404 body, a failed backend and query forwarding against captured openvoxdb shapes
This commit is contained in:
2026-09-12 17:58:38 +10:00
parent 94769a7864
commit eeb44057db
5 changed files with 446 additions and 6 deletions
+12 -1
View File
@@ -177,6 +177,12 @@ var queryRoutes = []route{
serve: (*Server).serveFirstHolder,
unsummed: "one backend holds the report, so nothing is merged across backends",
},
{
name: certnameRouteName,
matches: isCertnameRoute,
serve: (*Server).serveByOwner,
unsummed: "one certname's own data, from the backend that owns it; nothing is merged across backends",
},
}
// unmergedRoute answers every path no merged route claims.
@@ -907,8 +913,13 @@ func (s *Server) queryBackend(ctx context.Context, b Backend, path string, param
// The record shape is unknown, so a union would be guesswork: the first 2xx wins and the first error response is replayed when none succeeds.
func (s *Server) proxyUnmerged(w http.ResponseWriter, r *http.Request) {
s.proxyOrdered(w, r, s.cfg.Backends)
}
// proxyOrdered asks backends in the given order, which is what decides the answer when more than one of them holds the path.
func (s *Server) proxyOrdered(w http.ResponseWriter, r *http.Request, backends []Backend) {
var fallback *bufferedResponse
for _, b := range s.cfg.Backends {
for _, b := range backends {
resp, err := s.passThrough(r, b)
if err != nil {
s.log.Printf("warning: backend %q pass-through failed for %s: %v", b.Name, r.URL.Path, err)