mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-05 23:07:44 +00:00
ipn/ipnlocal: fix missing controlknobs.Knobs plumbing
I missed connecting some controlknobs.Knobs pieces in 4e91cf20a854 resulting in that breaking control knobs entirely. Whoops. The fix in ipn/ipnlocal (where it makes a new controlclient) but to atone, I also added integration tests. Those integration tests use a new "tailscale debug control-knobs" which by itself might be useful for future debugging. Updates #9351 Change-Id: Id9c89c8637746d879d5da67b9ac4e0d2367a3f0d Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
12d4685328
commit
7c1ed38ab3
@ -392,6 +392,20 @@ func (lc *LocalClient) DebugAction(ctx context.Context, action string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DebugResultJSON invokes a debug action and returns its result as something JSON-able.
|
||||
// These are development tools and subject to change or removal over time.
|
||||
func (lc *LocalClient) DebugResultJSON(ctx context.Context, action string) (any, error) {
|
||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error %w: %s", err, body)
|
||||
}
|
||||
var x any
|
||||
if err := json.Unmarshal(body, &x); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// DebugPortmapOpts contains options for the DebugPortmap command.
|
||||
type DebugPortmapOpts struct {
|
||||
// Duration is how long the mapping should be created for. It defaults
|
||||
|
@ -138,6 +138,11 @@
|
||||
Exec: localAPIAction("break-derp-conns"),
|
||||
ShortHelp: "break any open DERP connections from the daemon",
|
||||
},
|
||||
{
|
||||
Name: "control-knobs",
|
||||
Exec: debugControlKnobs,
|
||||
ShortHelp: "see current control knobs",
|
||||
},
|
||||
{
|
||||
Name: "prefs",
|
||||
Exec: runPrefs,
|
||||
@ -915,3 +920,17 @@ func runPeerEndpointChanges(ctx context.Context, args []string) error {
|
||||
fmt.Printf("%s", dst.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
func debugControlKnobs(ctx context.Context, args []string) error {
|
||||
if len(args) > 0 {
|
||||
return errors.New("unexpected arguments")
|
||||
}
|
||||
v, err := localClient.DebugResultJSON(ctx, "control-knobs")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e := json.NewEncoder(os.Stdout)
|
||||
e.SetIndent("", " ")
|
||||
e.Encode(v)
|
||||
return nil
|
||||
}
|
||||
|
@ -39,3 +39,19 @@ type Knobs struct {
|
||||
// running in magicsock, even when idle.
|
||||
ForceBackgroundSTUN atomic.Bool
|
||||
}
|
||||
|
||||
// AsDebugJSON returns k as something that can be marshalled with json.Marshal
|
||||
// for debug.
|
||||
func (k *Knobs) AsDebugJSON() map[string]any {
|
||||
if k == nil {
|
||||
return nil
|
||||
}
|
||||
return map[string]any{
|
||||
"DisableUPnP": k.DisableUPnP.Load(),
|
||||
"DisableDRPO": k.DisableDRPO.Load(),
|
||||
"KeepFullWGConfig": k.KeepFullWGConfig.Load(),
|
||||
"RandomizeClientPort": k.RandomizeClientPort.Load(),
|
||||
"OneCGNAT": k.OneCGNAT.Load(),
|
||||
"ForceBackgroundSTUN": k.ForceBackgroundSTUN.Load(),
|
||||
}
|
||||
}
|
||||
|
@ -1462,6 +1462,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error {
|
||||
Observer: b,
|
||||
C2NHandler: http.HandlerFunc(b.handleC2N),
|
||||
DialPlan: &b.dialPlan, // pointer because it can't be copied
|
||||
ControlKnobs: b.sys.ControlKnobs(),
|
||||
|
||||
// Don't warn about broken Linux IP forwarding when
|
||||
// netstack is being used.
|
||||
|
@ -557,6 +557,13 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) {
|
||||
err = h.b.DebugBreakTCPConns()
|
||||
case "break-derp-conns":
|
||||
err = h.b.DebugBreakDERPConns()
|
||||
case "control-knobs":
|
||||
k := h.b.ControlKnobs()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err = json.NewEncoder(w).Encode(k.AsDebugJSON())
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
case "":
|
||||
err = fmt.Errorf("missing parameter 'action'")
|
||||
default:
|
||||
|
@ -119,6 +119,36 @@ func TestOneNodeExpiredKey(t *testing.T) {
|
||||
d1.MustCleanShutdown(t)
|
||||
}
|
||||
|
||||
func TestControlKnobs(t *testing.T) {
|
||||
t.Parallel()
|
||||
env := newTestEnv(t)
|
||||
n1 := newTestNode(t, env)
|
||||
|
||||
d1 := n1.StartDaemon()
|
||||
defer d1.MustCleanShutdown(t)
|
||||
n1.AwaitResponding()
|
||||
n1.MustUp()
|
||||
|
||||
t.Logf("Got IP: %v", n1.AwaitIP())
|
||||
n1.AwaitRunning()
|
||||
|
||||
cmd := n1.Tailscale("debug", "control-knobs")
|
||||
cmd.Stdout = nil // in case --verbose-tailscale was set
|
||||
cmd.Stderr = nil // in case --verbose-tailscale was set
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("control-knobs output:\n%s", out)
|
||||
var m map[string]any
|
||||
if err := json.Unmarshal(out, &m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := m["DisableUPnP"], true; got != want {
|
||||
t.Errorf("control-knobs DisableUPnP = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectPanic(t *testing.T) {
|
||||
t.Parallel()
|
||||
env := newTestEnv(t)
|
||||
|
Loading…
x
Reference in New Issue
Block a user