mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-23 09:21:41 +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
|
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.
|
// DebugPortmapOpts contains options for the DebugPortmap command.
|
||||||
type DebugPortmapOpts struct {
|
type DebugPortmapOpts struct {
|
||||||
// Duration is how long the mapping should be created for. It defaults
|
// Duration is how long the mapping should be created for. It defaults
|
||||||
|
@ -138,6 +138,11 @@ var debugCmd = &ffcli.Command{
|
|||||||
Exec: localAPIAction("break-derp-conns"),
|
Exec: localAPIAction("break-derp-conns"),
|
||||||
ShortHelp: "break any open DERP connections from the daemon",
|
ShortHelp: "break any open DERP connections from the daemon",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "control-knobs",
|
||||||
|
Exec: debugControlKnobs,
|
||||||
|
ShortHelp: "see current control knobs",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "prefs",
|
Name: "prefs",
|
||||||
Exec: runPrefs,
|
Exec: runPrefs,
|
||||||
@ -915,3 +920,17 @@ func runPeerEndpointChanges(ctx context.Context, args []string) error {
|
|||||||
fmt.Printf("%s", dst.String())
|
fmt.Printf("%s", dst.String())
|
||||||
return nil
|
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.
|
// running in magicsock, even when idle.
|
||||||
ForceBackgroundSTUN atomic.Bool
|
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,
|
Observer: b,
|
||||||
C2NHandler: http.HandlerFunc(b.handleC2N),
|
C2NHandler: http.HandlerFunc(b.handleC2N),
|
||||||
DialPlan: &b.dialPlan, // pointer because it can't be copied
|
DialPlan: &b.dialPlan, // pointer because it can't be copied
|
||||||
|
ControlKnobs: b.sys.ControlKnobs(),
|
||||||
|
|
||||||
// Don't warn about broken Linux IP forwarding when
|
// Don't warn about broken Linux IP forwarding when
|
||||||
// netstack is being used.
|
// netstack is being used.
|
||||||
|
@ -557,6 +557,13 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) {
|
|||||||
err = h.b.DebugBreakTCPConns()
|
err = h.b.DebugBreakTCPConns()
|
||||||
case "break-derp-conns":
|
case "break-derp-conns":
|
||||||
err = h.b.DebugBreakDERPConns()
|
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 "":
|
case "":
|
||||||
err = fmt.Errorf("missing parameter 'action'")
|
err = fmt.Errorf("missing parameter 'action'")
|
||||||
default:
|
default:
|
||||||
|
@ -119,6 +119,36 @@ func TestOneNodeExpiredKey(t *testing.T) {
|
|||||||
d1.MustCleanShutdown(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) {
|
func TestCollectPanic(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
env := newTestEnv(t)
|
env := newTestEnv(t)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user