Added webapp Dashboard + logic to interact with server.
[src/xds/xds-agent.git] / lib / agent / apiv1-exec.go
1 package agent
2
3 import (
4         "encoding/json"
5         "io/ioutil"
6         "net/http"
7
8         "github.com/gin-gonic/gin"
9         common "github.com/iotbzh/xds-common/golib"
10 )
11
12 // Only define useful fields
13 type ExecArgs struct {
14         ID string `json:"id" binding:"required"`
15 }
16
17 // ExecCmd executes remotely a command
18 func (s *APIService) execCmd(c *gin.Context) {
19         s._execRequest("/exec", c)
20 }
21
22 // execSignalCmd executes remotely a command
23 func (s *APIService) execSignalCmd(c *gin.Context) {
24         s._execRequest("/signal", c)
25 }
26
27 func (s *APIService) _execRequest(url string, c *gin.Context) {
28         data, err := c.GetRawData()
29         if err != nil {
30                 common.APIError(c, err.Error())
31         }
32
33         // First get Project ID to retrieve Server ID and send command to right server
34         id := c.Param("id")
35         if id == "" {
36                 args := ExecArgs{}
37                 // XXX - we cannot use c.BindJSON, so directly unmarshall it
38                 // (see https://github.com/gin-gonic/gin/issues/1078)
39                 if err := json.Unmarshal(data, &args); err != nil {
40                         common.APIError(c, "Invalid arguments")
41                         return
42                 }
43                 id = args.ID
44         }
45         prj := s.projects.Get(id)
46         if prj == nil {
47                 common.APIError(c, "Unknown id")
48                 return
49         }
50
51         svr := (*prj).GetServer()
52         if svr == nil {
53                 common.APIError(c, "Cannot identify XDS Server")
54                 return
55         }
56
57         // Retrieve session info
58         sess := s.sessions.Get(c)
59         if sess == nil {
60                 common.APIError(c, "Unknown sessions")
61                 return
62         }
63         sock := sess.IOSocket
64         if sock == nil {
65                 common.APIError(c, "Websocket not established")
66                 return
67         }
68
69         // Forward XDSServer WS events to client WS
70         // TODO removed static event name list and get it from XDSServer
71         for _, evName := range []string{
72                 "exec:input",
73                 "exec:output",
74                 "exec:exit",
75                 "exec:inferior-input",
76                 "exec:inferior-output",
77         } {
78                 evN := evName
79                 svr.EventOn(evN, func(evData interface{}) {
80                         (*sock).Emit(evN, evData)
81                 })
82         }
83
84         // Forward back command to right server
85         response, err := svr.HTTPPostBody(url, string(data))
86         if err != nil {
87                 common.APIError(c, err.Error())
88                 return
89         }
90
91         // Decode response
92         body, err := ioutil.ReadAll(response.Body)
93         if err != nil {
94                 common.APIError(c, "Cannot read response body")
95                 return
96         }
97         c.JSON(http.StatusOK, string(body))
98
99 }