Files
tailscale/feature/tailnetlock/tailnetlock.go
Simon Law 3093e4523c feature/tailnetlock/tslockjsonv1: turn print functions into JSON converters
This patch pulls the printing and JSON-encoding out of
feature/tailnetlock/tslockjsonv1 into their callers, so that this
package only handles type conversions.

In cmd/tailscale/cli/tailnet-lock.go, it extracts the
printTailnetLockStatus function from runTailnetLockStatus to mirror
printTailnetLockLog and runTailnetLockLog.

Updates #17613

Signed-off-by: Simon Law <sfllaw@tailscale.com>
2026-07-30 16:23:09 -04:00

62 lines
1.6 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Package tailnetlock registers the tailnet lock debug C2N handler. In the
// future, all tailnet lock code should move here.
package tailnetlock
import (
jsonv1 "encoding/json"
"fmt"
"net/http"
"strconv"
"tailscale.com/feature"
"tailscale.com/feature/buildfeatures"
"tailscale.com/feature/tailnetlock/tslockjsonv1"
"tailscale.com/ipn/ipnlocal"
)
func init() {
feature.Register("tailnetlock")
ipnlocal.RegisterC2N("/debug/tka/log", handleC2NDebugTKALog)
}
const defaultC2NLogLimit = 50
const maxC2NLogLimit = 1000
func handleC2NDebugTKALog(b *ipnlocal.LocalBackend, w http.ResponseWriter, r *http.Request) {
if !buildfeatures.HasDebug {
http.Error(w, feature.ErrUnavailable.Error(), http.StatusNotImplemented)
return
}
logf := b.Logger()
logf("c2n: %s %s received", r.Method, r.URL)
limit := defaultC2NLogLimit
limitStr := r.URL.Query().Get("limit")
if limitStr != "" {
if parsed, err := strconv.Atoi(limitStr); err == nil {
limit = min(parsed, maxC2NLogLimit)
}
}
updates, err := b.TailnetLockLog(limit)
if ipnlocal.IsTailnetLockNotActive(err) {
http.Error(w, "tailnet lock not active", http.StatusBadRequest)
return
} else if err != nil {
http.Error(w, fmt.Sprintf("failed to get tailnet lock log: %v", err), http.StatusInternalServerError)
return
}
resp, err := tslockjsonv1.LogResponse(updates)
if err != nil {
http.Error(w, fmt.Sprintf("failed to get tailnet lock log: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
jsonv1.NewEncoder(w).Encode(resp)
}