Canvas: Add VM/PROXY dev modes support
- Update ServiceSchema to discriminate between VM and PROXY dev modes
- Add DevDisabled, DevVM, DevProxy TypeScript types
- Update ServiceData type in graph.ts for new dev structure
- Update generateDodoConfig to handle both VM and PROXY modes
- Update configToGraph to properly convert dev configurations
- Maintain backward compatibility with existing dev configurations
- Update UI and introduce two new DevVM and DevProxy components
- Fetch user machine list from headscale API
Change-Id: I8f9df4ab9bd34c049fffadb748115335e8260a54
diff --git a/core/headscale/client.go b/core/headscale/client.go
index f4d0f51..766ae52 100644
--- a/core/headscale/client.go
+++ b/core/headscale/client.go
@@ -96,14 +96,22 @@
IPAddresses []net.IP `json:"ip_addresses"`
}
-func (c *client) getNodeId(user, node string) (string, error) {
+func (c *client) getUserNodes(user string) ([]nodeInfo, error) {
cmd := exec.Command("headscale", c.config, "--user", user, "node", "list", "-o", "json")
out, err := cmd.Output()
if err != nil {
- return "", err
+ return nil, err
}
var nodes []nodeInfo
if err := json.NewDecoder(bytes.NewReader(out)).Decode(&nodes); err != nil {
+ return nil, err
+ }
+ return nodes, nil
+}
+
+func (c *client) getNodeId(user, node string) (string, error) {
+ nodes, err := c.getUserNodes(user)
+ if err != nil {
return "", err
}
for _, n := range nodes {
diff --git a/core/headscale/main.go b/core/headscale/main.go
index 8a3a9ec..fb20274 100644
--- a/core/headscale/main.go
+++ b/core/headscale/main.go
@@ -112,6 +112,7 @@
r.HandleFunc("/user/{user}/node/{node}/expire", s.expireUserNode).Methods(http.MethodPost)
r.HandleFunc("/user/{user}/node/{node}/ip", s.getNodeIP).Methods(http.MethodGet)
r.HandleFunc("/user/{user}/node/{node}", s.removeUserNode).Methods(http.MethodDelete)
+ 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)
go func() {
@@ -224,6 +225,24 @@
}
}
+func (s *server) getUserNodes(w http.ResponseWriter, r *http.Request) {
+ user, ok := mux.Vars(r)["user"]
+ if !ok {
+ http.Error(w, "no user", http.StatusBadRequest)
+ return
+ }
+ nodes, err := s.client.getUserNodes(user)
+ if err != nil {
+ if errors.Is(err, ErrorNotFound) {
+ http.Error(w, err.Error(), http.StatusNotFound)
+ } else {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ return
+ }
+ json.NewEncoder(w).Encode(nodes)
+}
+
func (s *server) handleSyncUsers(_ http.ResponseWriter, _ *http.Request) {
go s.syncUsers()
}