1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-09-25 17:51:11 +02:00

implemnted the registration-cache endpoint

This commit is contained in:
Shourya Gautam 2025-08-19 21:45:26 +05:30
parent 086fcad7d9
commit fff395e837
3 changed files with 53 additions and 3 deletions

View File

@ -105,10 +105,9 @@ func (h *Headscale) debugHTTPServer() *http.Server {
w.Write(dmJSON) w.Write(dmJSON)
})) }))
debug.Handle("registration-cache", "Pending registrations", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { debug.Handle("registration-cache", "Pending registrations", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// TODO(kradalby): This should be replaced with a proper state method that returns registration info w.Header().Set("Content-Type", "text/plain")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write([]byte("{}")) // For now, return empty object w.Write([]byte(h.state.GetRegistrationCacheDebug()))
})) }))
debug.Handle("routes", "Routes", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { debug.Handle("routes", "Routes", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")

View File

@ -9,6 +9,7 @@ import (
"io" "io"
"net/netip" "net/netip"
"os" "os"
"strings"
"time" "time"
hsdb "github.com/juanfont/headscale/hscontrol/db" hsdb "github.com/juanfont/headscale/hscontrol/db"
@ -736,6 +737,43 @@ func (s *State) SetRegistrationCacheEntry(id types.RegistrationID, entry types.R
s.registrationCache.Set(id, entry) s.registrationCache.Set(id, entry)
} }
// GetRegistrationCacheDebug returns all registration cache entries as a formatted string
func (s *State) GetRegistrationCacheDebug() string {
s.mu.RLock()
defer s.mu.RUnlock()
items := s.registrationCache.Items()
if len(items) == 0 {
return "No pending registrations"
}
var result strings.Builder
result.WriteString(fmt.Sprintf("Registration Cache (%d entries):\n", len(items)))
result.WriteString("=====================================\n")
for id, item := range items {
regNode := item.Object
result.WriteString(fmt.Sprintf(" ID: %s\n", id))
result.WriteString(fmt.Sprintf(" Node ID: %d\n", regNode.Node.ID))
result.WriteString(fmt.Sprintf(" Hostname: %s\n", regNode.Node.Hostname))
result.WriteString(fmt.Sprintf(" Given Name: %s\n", regNode.Node.GivenName))
result.WriteString(fmt.Sprintf(" User ID: %d\n", regNode.Node.UserID))
result.WriteString(fmt.Sprintf(" Register Method: %s\n", regNode.Node.RegisterMethod))
result.WriteString(fmt.Sprintf(" Expires: %v\n", item.Expiration))
result.WriteString(fmt.Sprintf(" Channel Status: %s\n", func() string {
select {
case <-regNode.Registered:
return "closed"
default:
return "open"
}
}()))
result.WriteString("-------------------------------------\n")
}
return result.String()
}
// HandleNodeFromAuthPath handles node registration through authentication flow (like OIDC). // HandleNodeFromAuthPath handles node registration through authentication flow (like OIDC).
func (s *State) HandleNodeFromAuthPath( func (s *State) HandleNodeFromAuthPath(
registrationID types.RegistrationID, registrationID types.RegistrationID,

View File

@ -188,6 +188,19 @@ type RegisterNode struct {
Registered chan *Node Registered chan *Node
} }
// RegisterNodeDebug is a JSON-serializable version of RegisterNode
// that excludes the channel field to prevent JSON marshaling errors
type RegisterNodeDebug struct {
Node Node `json:"node"`
}
// ToDebug converts a RegisterNode to its JSON-serializable form
func (rn *RegisterNode) ToDebug() RegisterNodeDebug {
return RegisterNodeDebug{
Node: rn.Node,
}
}
// DefaultBatcherWorkers returns the default number of batcher workers. // DefaultBatcherWorkers returns the default number of batcher workers.
// Default to 3/4 of CPU cores, minimum 1, no maximum. // Default to 3/4 of CPU cores, minimum 1, no maximum.
func DefaultBatcherWorkers() int { func DefaultBatcherWorkers() int {