all: mechanical lint fixes
hscontrol/debug.go — pre-size nodes []nodeStatus to len(debugInfo)
so the loop does not grow under append.
hscontrol/mapper/batcher_test.go — testing.TB parameter on
setupBatcherWithTestData renamed t → tb so thelper sees the
expected name.
hscontrol/db/text_serialiser.go — reflect.Ptr → reflect.Pointer
(deprecated alias).
This commit is contained in:
parent
e00c899219
commit
f905d58292
@ -24,7 +24,7 @@ func isTextUnmarshaler(rv reflect.Value) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func maybeInstantiatePtr(rv reflect.Value) {
|
func maybeInstantiatePtr(rv reflect.Value) {
|
||||||
if rv.Kind() == reflect.Ptr && rv.IsNil() {
|
if rv.Kind() == reflect.Pointer && rv.IsNil() {
|
||||||
np := reflect.New(rv.Type().Elem())
|
np := reflect.New(rv.Type().Elem())
|
||||||
rv.Set(np)
|
rv.Set(np)
|
||||||
}
|
}
|
||||||
@ -34,8 +34,8 @@ func decodingError(name string, err error) error {
|
|||||||
return fmt.Errorf("decoding to %s: %w", name, err)
|
return fmt.Errorf("decoding to %s: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextSerialiser implements the Serialiser interface for fields that
|
// TextSerialiser implements the [schema.SerializerInterface] for fields that
|
||||||
// have a type that implements encoding.TextUnmarshaler.
|
// have a type that implements [encoding.TextUnmarshaler].
|
||||||
type TextSerialiser struct{}
|
type TextSerialiser struct{}
|
||||||
|
|
||||||
func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue any) error {
|
func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue any) error {
|
||||||
@ -43,7 +43,7 @@ func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect
|
|||||||
|
|
||||||
// If the field is a pointer, we need to dereference it to get the actual type
|
// If the field is a pointer, we need to dereference it to get the actual type
|
||||||
// so we do not end with a second pointer.
|
// so we do not end with a second pointer.
|
||||||
if fieldValue.Elem().Kind() == reflect.Ptr {
|
if fieldValue.Elem().Kind() == reflect.Pointer {
|
||||||
fieldValue = fieldValue.Elem()
|
fieldValue = fieldValue.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect
|
|||||||
// If it is not a pointer, we need to assign the value to the
|
// If it is not a pointer, we need to assign the value to the
|
||||||
// field.
|
// field.
|
||||||
dstField := field.ReflectValueOf(ctx, dst)
|
dstField := field.ReflectValueOf(ctx, dst)
|
||||||
if dstField.Kind() == reflect.Ptr {
|
if dstField.Kind() == reflect.Pointer {
|
||||||
dstField.Set(fieldValue)
|
dstField.Set(fieldValue)
|
||||||
} else {
|
} else {
|
||||||
dstField.Set(fieldValue.Elem())
|
dstField.Set(fieldValue.Elem())
|
||||||
@ -97,7 +97,7 @@ func (TextSerialiser) Value(ctx context.Context, field *schema.Field, dst reflec
|
|||||||
// If the value is nil, we return nil, however, go nil values are not
|
// If the value is nil, we return nil, however, go nil values are not
|
||||||
// always comparable, particularly when reflection is involved:
|
// always comparable, particularly when reflection is involved:
|
||||||
// https://dev.to/arxeiss/in-go-nil-is-not-equal-to-nil-sometimes-jn8
|
// https://dev.to/arxeiss/in-go-nil-is-not-equal-to-nil-sometimes-jn8
|
||||||
if v == nil || (reflect.ValueOf(v).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil()) {
|
if v == nil || (reflect.ValueOf(v).Kind() == reflect.Pointer && reflect.ValueOf(v).IsNil()) {
|
||||||
return nil, nil //nolint:nilnil // intentional: nil value for GORM serializer
|
return nil, nil //nolint:nilnil // intentional: nil value for GORM serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,9 +19,9 @@ import (
|
|||||||
"tailscale.com/tsweb"
|
"tailscale.com/tsweb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// protectedDebugHandler wraps an http.Handler with an access check that
|
// protectedDebugHandler wraps an [http.Handler] with an access check that
|
||||||
// allows requests from loopback, Tailscale CGNAT IPs, and private
|
// allows requests from loopback, Tailscale CGNAT IPs, and private
|
||||||
// (RFC 1918 / RFC 4193) addresses. This extends tsweb.Protected which
|
// (RFC 1918 / RFC 4193) addresses. This extends [tsweb.Protected] which
|
||||||
// only allows loopback and Tailscale IPs.
|
// only allows loopback and Tailscale IPs.
|
||||||
func protectedDebugHandler(h http.Handler) http.Handler {
|
func protectedDebugHandler(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -31,7 +31,7 @@ func protectedDebugHandler(h http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// tsweb.AllowDebugAccess rejects X-Forwarded-For and non-TS IPs.
|
// [tsweb.AllowDebugAccess] rejects X-Forwarded-For and non-TS IPs.
|
||||||
// Additionally allow private/LAN addresses so operators can reach
|
// Additionally allow private/LAN addresses so operators can reach
|
||||||
// debug endpoints from their local network without tailscaled.
|
// debug endpoints from their local network without tailscaled.
|
||||||
ipStr, _, err := net.SplitHostPort(r.RemoteAddr)
|
ipStr, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||||
@ -177,7 +177,7 @@ func (h *Headscale) debugHTTPServer() *http.Server {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// NodeStore endpoint
|
// [state.NodeStore] endpoint
|
||||||
debug.Handle("nodestore", "NodeStore information", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
debug.Handle("nodestore", "NodeStore information", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// Check Accept header to determine response format
|
// Check Accept header to determine response format
|
||||||
acceptHeader := r.Header.Get("Accept")
|
acceptHeader := r.Header.Get("Accept")
|
||||||
@ -301,7 +301,7 @@ func (h *Headscale) debugHTTPServer() *http.Server {
|
|||||||
_, _ = w.Write(resJSON)
|
_, _ = w.Write(resJSON)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Batcher endpoint
|
// [mapper.Batcher] endpoint
|
||||||
debug.Handle("batcher", "Batcher connected nodes", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
debug.Handle("batcher", "Batcher connected nodes", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// Check Accept header to determine response format
|
// Check Accept header to determine response format
|
||||||
acceptHeader := r.Header.Get("Accept")
|
acceptHeader := r.Header.Get("Accept")
|
||||||
@ -329,7 +329,7 @@ func (h *Headscale) debugHTTPServer() *http.Server {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Ping endpoint: sends a PingRequest to a node and waits for it to respond.
|
// Ping endpoint: sends a [tailcfg.PingRequest] to a node and waits for it to respond.
|
||||||
// Supports POST (form submit) and GET with ?node= (clickable quick-ping links).
|
// Supports POST (form submit) and GET with ?node= (clickable quick-ping links).
|
||||||
debug.Handle("ping", "Ping a node to check connectivity", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
debug.Handle("ping", "Ping a node to check connectivity", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
@ -361,12 +361,12 @@ func (h *Headscale) debugHTTPServer() *http.Server {
|
|||||||
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
_, _ = w.Write([]byte(templates.PingPage(query, result, nodes).Render()))
|
_, _ = w.Write([]byte(templates.PingPage(query, result, nodes).Render())) //nolint:gosec // G705: templ component auto-escapes
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// statsviz.Register would mount handlers directly on the raw mux,
|
// [statsviz.Register] would mount handlers directly on the raw mux,
|
||||||
// bypassing the access gate. Build the server by hand and wrap
|
// bypassing the access gate. Build the server by hand and wrap
|
||||||
// each handler with protectedDebugHandler.
|
// each handler with [protectedDebugHandler].
|
||||||
statsvizSrv, err := statsviz.NewServer()
|
statsvizSrv, err := statsviz.NewServer()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
debugMux.Handle("/debug/statsviz/", protectedDebugHandler(statsvizSrv.Index()))
|
debugMux.Handle("/debug/statsviz/", protectedDebugHandler(statsvizSrv.Index()))
|
||||||
@ -402,9 +402,9 @@ func (h *Headscale) debugBatcher() string {
|
|||||||
activeConnections int
|
activeConnections int
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodes []nodeStatus
|
|
||||||
|
|
||||||
debugInfo := h.mapBatcher.Debug()
|
debugInfo := h.mapBatcher.Debug()
|
||||||
|
nodes := make([]nodeStatus, 0, len(debugInfo))
|
||||||
|
|
||||||
for nodeID, info := range debugInfo {
|
for nodeID, info := range debugInfo {
|
||||||
nodes = append(nodes, nodeStatus{
|
nodes = append(nodes, nodeStatus{
|
||||||
id: nodeID,
|
id: nodeID,
|
||||||
@ -510,7 +510,7 @@ func (h *Headscale) connectedNodesList() []templates.ConnectedNode {
|
|||||||
|
|
||||||
const pingTimeout = 30 * time.Second
|
const pingTimeout = 30 * time.Second
|
||||||
|
|
||||||
// doPing sends a PingRequest to the node identified by query and waits for a response.
|
// doPing sends a [tailcfg.PingRequest] to the node identified by query and waits for a response.
|
||||||
func (h *Headscale) doPing(ctx context.Context, query string) *templates.PingResult {
|
func (h *Headscale) doPing(ctx context.Context, query string) *templates.PingResult {
|
||||||
if query == "" {
|
if query == "" {
|
||||||
return &templates.PingResult{
|
return &templates.PingResult{
|
||||||
|
|||||||
@ -158,14 +158,14 @@ type node struct {
|
|||||||
//
|
//
|
||||||
// Returns TestData struct containing all created entities and a cleanup function.
|
// Returns TestData struct containing all created entities and a cleanup function.
|
||||||
func setupBatcherWithTestData(
|
func setupBatcherWithTestData(
|
||||||
t testing.TB,
|
tb testing.TB,
|
||||||
bf batcherFunc,
|
bf batcherFunc,
|
||||||
userCount, nodesPerUser, bufferSize int,
|
userCount, nodesPerUser, bufferSize int,
|
||||||
) (*TestData, func()) {
|
) (*TestData, func()) {
|
||||||
t.Helper()
|
tb.Helper()
|
||||||
|
|
||||||
// Create database and populate with test data first
|
// Create database and populate with test data first
|
||||||
tmpDir := t.TempDir()
|
tmpDir := tb.TempDir()
|
||||||
dbPath := tmpDir + "/headscale_test.db"
|
dbPath := tmpDir + "/headscale_test.db"
|
||||||
|
|
||||||
prefixV4 := netip.MustParsePrefix("100.64.0.0/10")
|
prefixV4 := netip.MustParsePrefix("100.64.0.0/10")
|
||||||
@ -206,7 +206,7 @@ func setupBatcherWithTestData(
|
|||||||
// Create database and populate it with test data
|
// Create database and populate it with test data
|
||||||
database, err := db.NewHeadscaleDatabase(cfg)
|
database, err := db.NewHeadscaleDatabase(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("setting up database: %s", err)
|
tb.Fatalf("setting up database: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create test users and nodes in the database
|
// Create test users and nodes in the database
|
||||||
@ -226,12 +226,12 @@ func setupBatcherWithTestData(
|
|||||||
// Now create state using the same database
|
// Now create state using the same database
|
||||||
state, err := state.NewState(cfg)
|
state, err := state.NewState(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create state: %v", err)
|
tb.Fatalf("Failed to create state: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
derpMap, err := derp.GetDERPMap(cfg.DERP)
|
derpMap, err := derp.GetDERPMap(cfg.DERP)
|
||||||
require.NoError(t, err)
|
require.NoError(tb, err)
|
||||||
require.NotNil(t, derpMap)
|
require.NotNil(tb, derpMap)
|
||||||
|
|
||||||
state.SetDERPMap(derpMap)
|
state.SetDERPMap(derpMap)
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ func setupBatcherWithTestData(
|
|||||||
|
|
||||||
_, err = state.SetPolicy([]byte(allowAllPolicy))
|
_, err = state.SetPolicy([]byte(allowAllPolicy))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to set allow-all policy: %v", err)
|
tb.Fatalf("Failed to set allow-all policy: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create batcher with the state and wrap it for testing
|
// Create batcher with the state and wrap it for testing
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user