Headscale: Include last seen in node info
Add debugging API endpoint to run arbitrary headscale command.
Change-Id: I713d55b44d9657971c0ecb8befc8a1408e4b76af
diff --git a/core/headscale/main.go b/core/headscale/main.go
index fb20274..50917d7 100644
--- a/core/headscale/main.go
+++ b/core/headscale/main.go
@@ -115,6 +115,7 @@
r.HandleFunc("/user/{user}/node", s.getUserNodes).Methods(http.MethodGet)
r.HandleFunc("/user", s.createUser).Methods(http.MethodPost)
r.HandleFunc("/routes/{id}/enable", s.enableRoute).Methods(http.MethodPost)
+ r.HandleFunc("/cmd", s.runCmd).Methods(http.MethodPost)
go func() {
rand.Seed(uint64(time.Now().UnixNano()))
s.syncUsers()
@@ -127,6 +128,24 @@
return http.ListenAndServe(fmt.Sprintf(":%d", s.port), r)
}
+type cmdReq struct {
+ Cmd string `json:"cmd"`
+}
+
+func (s *server) runCmd(w http.ResponseWriter, r *http.Request) {
+ var req cmdReq
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ if out, err := s.client.run(strings.Split(req.Cmd, " ")...); err != nil && !errors.Is(err, ErrorAlreadyExists) {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ } else {
+ fmt.Fprint(w, out)
+ }
+}
+
type createUserReq struct {
Name string `json:"name"`
}