Added webapp Dashboard + logic to interact with server.
[src/xds/xds-agent.git] / lib / agent / apiv1-exec.go
diff --git a/lib/agent/apiv1-exec.go b/lib/agent/apiv1-exec.go
new file mode 100644 (file)
index 0000000..83ec7aa
--- /dev/null
@@ -0,0 +1,99 @@
+package agent
+
+import (
+       "encoding/json"
+       "io/ioutil"
+       "net/http"
+
+       "github.com/gin-gonic/gin"
+       common "github.com/iotbzh/xds-common/golib"
+)
+
+// Only define useful fields
+type ExecArgs struct {
+       ID string `json:"id" binding:"required"`
+}
+
+// ExecCmd executes remotely a command
+func (s *APIService) execCmd(c *gin.Context) {
+       s._execRequest("/exec", c)
+}
+
+// execSignalCmd executes remotely a command
+func (s *APIService) execSignalCmd(c *gin.Context) {
+       s._execRequest("/signal", c)
+}
+
+func (s *APIService) _execRequest(url string, c *gin.Context) {
+       data, err := c.GetRawData()
+       if err != nil {
+               common.APIError(c, err.Error())
+       }
+
+       // First get Project ID to retrieve Server ID and send command to right server
+       id := c.Param("id")
+       if id == "" {
+               args := ExecArgs{}
+               // XXX - we cannot use c.BindJSON, so directly unmarshall it
+               // (see https://github.com/gin-gonic/gin/issues/1078)
+               if err := json.Unmarshal(data, &args); err != nil {
+                       common.APIError(c, "Invalid arguments")
+                       return
+               }
+               id = args.ID
+       }
+       prj := s.projects.Get(id)
+       if prj == nil {
+               common.APIError(c, "Unknown id")
+               return
+       }
+
+       svr := (*prj).GetServer()
+       if svr == nil {
+               common.APIError(c, "Cannot identify XDS Server")
+               return
+       }
+
+       // Retrieve session info
+       sess := s.sessions.Get(c)
+       if sess == nil {
+               common.APIError(c, "Unknown sessions")
+               return
+       }
+       sock := sess.IOSocket
+       if sock == nil {
+               common.APIError(c, "Websocket not established")
+               return
+       }
+
+       // Forward XDSServer WS events to client WS
+       // TODO removed static event name list and get it from XDSServer
+       for _, evName := range []string{
+               "exec:input",
+               "exec:output",
+               "exec:exit",
+               "exec:inferior-input",
+               "exec:inferior-output",
+       } {
+               evN := evName
+               svr.EventOn(evN, func(evData interface{}) {
+                       (*sock).Emit(evN, evData)
+               })
+       }
+
+       // Forward back command to right server
+       response, err := svr.HTTPPostBody(url, string(data))
+       if err != nil {
+               common.APIError(c, err.Error())
+               return
+       }
+
+       // Decode response
+       body, err := ioutil.ReadAll(response.Body)
+       if err != nil {
+               common.APIError(c, "Cannot read response body")
+               return
+       }
+       c.JSON(http.StatusOK, string(body))
+
+}