mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-08 09:07:44 +00:00
cmd/tailscale, ipn/ipnlocal: add debug command to write to StateStore for dev
Not for end users (unless directed by support). Mostly for ease of development for some upcoming webserver work. Change-Id: I43acfed217514567acb3312367b24d620e739f88 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
bf2d3cd074
commit
5bb7e0307c
@ -348,6 +348,19 @@ func (lc *LocalClient) DebugAction(ctx context.Context, action string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDevStoreKeyValue set a statestore key/value. It's only meant for development.
|
||||||
|
// The schema (including when keys are re-read) is not a stable interface.
|
||||||
|
func (lc *LocalClient) SetDevStoreKeyValue(ctx context.Context, key, value string) error {
|
||||||
|
body, err := lc.send(ctx, "POST", "/localapi/v0/dev-set-state-store?"+(url.Values{
|
||||||
|
"key": {key},
|
||||||
|
"value": {value},
|
||||||
|
}).Encode(), 200, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error %w: %s", err, body)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetComponentDebugLogging sets component's debug logging enabled for
|
// SetComponentDebugLogging sets component's debug logging enabled for
|
||||||
// the provided duration. If the duration is in the past, the debug logging
|
// the provided duration. If the duration is in the past, the debug logging
|
||||||
// is disabled.
|
// is disabled.
|
||||||
|
@ -144,6 +144,16 @@
|
|||||||
return fs
|
return fs
|
||||||
})(),
|
})(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "dev-store-set",
|
||||||
|
Exec: runDevStoreSet,
|
||||||
|
ShortHelp: "set a key/value pair during development",
|
||||||
|
FlagSet: (func() *flag.FlagSet {
|
||||||
|
fs := newFlagSet("store-set")
|
||||||
|
fs.BoolVar(&devStoreSetArgs.danger, "danger", false, "accept danger")
|
||||||
|
return fs
|
||||||
|
})(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,3 +556,17 @@ func runDebugComponentLogs(ctx context.Context, args []string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var devStoreSetArgs struct {
|
||||||
|
danger bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDevStoreSet(ctx context.Context, args []string) error {
|
||||||
|
if len(args) != 2 {
|
||||||
|
return errors.New("usage: dev-store-set --danger <key> <value>")
|
||||||
|
}
|
||||||
|
if !devStoreSetArgs.danger {
|
||||||
|
return errors.New("this command is dangerous; use --danger to proceed")
|
||||||
|
}
|
||||||
|
return localClient.SetDevStoreKeyValue(ctx, args[0], args[1])
|
||||||
|
}
|
||||||
|
@ -3966,3 +3966,15 @@ func (b *LocalBackend) Doctor(ctx context.Context, logf logger.Logf) {
|
|||||||
|
|
||||||
doctor.RunChecks(ctx, logf, checks...)
|
doctor.RunChecks(ctx, logf, checks...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDevStateStore updates the LocalBackend's state storage to the provided values.
|
||||||
|
//
|
||||||
|
// It's meant only for development.
|
||||||
|
func (b *LocalBackend) SetDevStateStore(key, value string) error {
|
||||||
|
if b.store == nil {
|
||||||
|
return errors.New("no state store")
|
||||||
|
}
|
||||||
|
err := b.store.WriteState(ipn.StateKey(key), []byte(value))
|
||||||
|
b.logf("SetDevStateStore(%q, %q) = %v", key, value, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
"component-debug-logging": (*Handler).serveComponentDebugLogging,
|
"component-debug-logging": (*Handler).serveComponentDebugLogging,
|
||||||
"debug": (*Handler).serveDebug,
|
"debug": (*Handler).serveDebug,
|
||||||
"derpmap": (*Handler).serveDERPMap,
|
"derpmap": (*Handler).serveDERPMap,
|
||||||
|
"dev-set-state-store": (*Handler).serveDevSetStateStore,
|
||||||
"dial": (*Handler).serveDial,
|
"dial": (*Handler).serveDial,
|
||||||
"file-targets": (*Handler).serveFileTargets,
|
"file-targets": (*Handler).serveFileTargets,
|
||||||
"goroutines": (*Handler).serveGoroutines,
|
"goroutines": (*Handler).serveGoroutines,
|
||||||
@ -401,6 +402,23 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) {
|
|||||||
io.WriteString(w, "done\n")
|
io.WriteString(w, "done\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) serveDevSetStateStore(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !h.PermitWrite {
|
||||||
|
http.Error(w, "debug access denied", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.Method != "POST" {
|
||||||
|
http.Error(w, "POST required", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.b.SetDevStateStore(r.FormValue("key"), r.FormValue("value")); err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "text/plain")
|
||||||
|
io.WriteString(w, "done\n")
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) serveComponentDebugLogging(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) serveComponentDebugLogging(w http.ResponseWriter, r *http.Request) {
|
||||||
if !h.PermitWrite {
|
if !h.PermitWrite {
|
||||||
http.Error(w, "debug access denied", http.StatusForbidden)
|
http.Error(w, "debug access denied", http.StatusForbidden)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user