8 "github.com/gin-gonic/gin"
9 "github.com/iotbzh/xds-agent/lib/apiv1"
10 common "github.com/iotbzh/xds-common/golib"
11 uuid "github.com/satori/go.uuid"
15 var fwdFuncID []uuid.UUID
17 // ExecCmd executes remotely a command
18 func (s *APIService) execCmd(c *gin.Context) {
19 s._execRequest("/exec", c)
22 // execSignalCmd executes remotely a command
23 func (s *APIService) execSignalCmd(c *gin.Context) {
24 s._execRequest("/signal", c)
27 func (s *APIService) _execRequest(cmd string, c *gin.Context) {
28 data, err := c.GetRawData()
30 common.APIError(c, err.Error())
33 args := apiv1.ExecArgs{}
34 // XXX - we cannot use c.BindJSON, so directly unmarshall it
35 // (see https://github.com/gin-gonic/gin/issues/1078)
36 if err := json.Unmarshal(data, &args); err != nil {
37 common.APIError(c, "Invalid arguments")
41 // First get Project ID to retrieve Server ID and send command to right server
46 id, err := s.projects.ResolveID(iid)
48 common.APIError(c, err.Error())
51 prj := s.projects.Get(id)
53 common.APIError(c, "Unknown id")
57 svr := (*prj).GetServer()
59 common.APIError(c, "Cannot identify XDS Server")
63 // Retrieve session info
64 sess := s.sessions.Get(c)
66 common.APIError(c, "Unknown sessions")
71 common.APIError(c, "Websocket not established")
75 // Forward XDSServer WS events to client WS
76 // TODO removed static event name list and get it from XDSServer
80 apiv1.ExecInferiorInEvent,
81 apiv1.ExecInferiorOutEvent,
84 for _, evName := range evtList {
86 fwdFunc := func(pData interface{}, evData interface{}) error {
88 // IO socket can be nil when disconnected
89 so := s.sessions.IOSocketGet(sid)
91 s.Log.Infof("%s not emitted: WS closed (sid:%s)", evN, sid)
95 // Forward event to Client/Dashboard
96 (*so).Emit(evN, evData)
99 id, err := svr.EventOn(evN, sess.ID, fwdFunc)
101 common.APIError(c, err.Error())
104 fwdFuncID = append(fwdFuncID, id)
107 // Handle Exit event separately to cleanup registered listener
108 var exitFuncID uuid.UUID
109 exitFunc := func(pData interface{}, evData interface{}) error {
110 evN := apiv1.ExecExitEvent
111 sid := pData.(string)
113 // IO socket can be nil when disconnected
114 so := s.sessions.IOSocketGet(sid)
116 s.Log.Infof("%s not emitted: WS closed (sid:%s)", evN, sid)
120 (*so).Emit(evN, evData)
123 for i, evName := range evtList {
124 svr.EventOff(evName, fwdFuncID[i])
126 svr.EventOff(evN, exitFuncID)
130 exitFuncID, err = svr.EventOn(apiv1.ExecExitEvent, sess.ID, exitFunc)
132 common.APIError(c, err.Error())
136 // Forward back command to right server
137 response, err := svr.SendCommand(cmd, data)
139 common.APIError(c, err.Error())
144 body, err := ioutil.ReadAll(response.Body)
146 common.APIError(c, "Cannot read response body")
149 c.JSON(http.StatusOK, string(body))