summaryrefslogtreecommitdiffstats
path: root/lib/agent/apiv1-exec.go
diff options
context:
space:
mode:
authorSebastien Douheret <sebastien.douheret@iot.bzh>2017-11-29 11:06:15 +0100
committerSebastien Douheret <sebastien.douheret@iot.bzh>2017-11-29 15:24:28 +0100
commit32791ffed5bdfaa698e90f9c067dc6e8ababbfc3 (patch)
treeb537f4607f54b43c9d994a4f7d32f18d84d2962b /lib/agent/apiv1-exec.go
parent7c7d90a781082c6bd22d12a5e2451ca61a5198af (diff)
Fixed /exec input stream and /signal.
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
Diffstat (limited to 'lib/agent/apiv1-exec.go')
-rw-r--r--lib/agent/apiv1-exec.go159
1 files changed, 119 insertions, 40 deletions
diff --git a/lib/agent/apiv1-exec.go b/lib/agent/apiv1-exec.go
index 3cb4d23..5fdfb9d 100644
--- a/lib/agent/apiv1-exec.go
+++ b/lib/agent/apiv1-exec.go
@@ -1,37 +1,22 @@
package agent
import (
- "encoding/json"
- "io/ioutil"
"net/http"
"github.com/franciscocpg/reflectme"
"github.com/gin-gonic/gin"
- "github.com/iotbzh/xds-agent/lib/apiv1"
+ "github.com/iotbzh/xds-agent/lib/xaapiv1"
common "github.com/iotbzh/xds-common/golib"
+ "github.com/iotbzh/xds-server/lib/xsapiv1"
uuid "github.com/satori/go.uuid"
)
// 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(cmd string, c *gin.Context) {
- data, err := c.GetRawData()
- if err != nil {
- common.APIError(c, err.Error())
- }
- args := apiv1.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 {
+ args := xaapiv1.ExecArgs{}
+ if err := c.BindJSON(&args); err != nil {
+ s.Log.Warningf("/exec invalid args, err=%v", err)
common.APIError(c, "Invalid arguments")
return
}
@@ -70,17 +55,36 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) {
return
}
- // Forward XDSServer WS events to client WS
- // TODO removed static event name list and get it from XDSServer
- evtList := []string{
- apiv1.ExecInEvent,
- apiv1.ExecOutEvent,
- apiv1.ExecInferiorInEvent,
- apiv1.ExecInferiorOutEvent,
+ // Forward input events from client to XDSServer through WS
+ // TODO use XDSServer events names definition
+ evtInList := []string{
+ xaapiv1.ExecInEvent,
+ xaapiv1.ExecInferiorInEvent,
+ }
+ for _, evName := range evtInList {
+ evN := evName
+ err := (*sock).On(evN, func(stdin string) {
+ if s.LogLevelSilly {
+ s.Log.Debugf("EXEC EVENT IN (%s) <<%v>>", evN, stdin)
+ }
+ svr.EventEmit(evN, stdin)
+ })
+ if err != nil {
+ msgErr := "Error while registering WS for " + evN + " event"
+ s.Log.Errorf(msgErr, ", err: %v", err)
+ common.APIError(c, msgErr)
+ return
+ }
}
+ // Forward output events from XDSServer to client through WS
+ // TODO use XDSServer events names definition
var fwdFuncID []uuid.UUID
- for _, evName := range evtList {
+ evtOutList := []string{
+ xaapiv1.ExecOutEvent,
+ xaapiv1.ExecInferiorOutEvent,
+ }
+ for _, evName := range evtOutList {
evN := evName
fwdFunc := func(pData interface{}, evData interface{}) error {
sid := pData.(string)
@@ -94,6 +98,10 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) {
// Add sessionID to event Data
reflectme.SetField(evData, "sessionID", sid)
+ if s.LogLevelSilly {
+ s.Log.Debugf("EXEC EVENT OUT (%s) <<%v>>", evN, evData)
+ }
+
// Forward event to Client/Dashboard
(*so).Emit(evN, evData)
return nil
@@ -108,9 +116,12 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) {
// Handle Exit event separately to cleanup registered listener
var exitFuncID uuid.UUID
- exitFunc := func(pData interface{}, evData interface{}) error {
- evN := apiv1.ExecExitEvent
- sid := pData.(string)
+ exitFunc := func(privD interface{}, evData interface{}) error {
+ evN := xaapiv1.ExecExitEvent
+
+ pData := privD.(map[string]string)
+ sid := pData["sessID"]
+ prjID := pData["prjID"]
// Add sessionID to event Data
reflectme.SetField(evData, "sessionID", sid)
@@ -123,32 +134,100 @@ func (s *APIService) _execRequest(cmd string, c *gin.Context) {
s.Log.Infof("%s not emitted: WS closed (sid:%s)", evN, sid)
}
+ prj := s.projects.Get(prjID)
+ if prj != nil {
+ evD := evData.(map[string]interface{})
+ cmdIDData, cmdIDExist := evD["cmdID"]
+ svr := (*prj).GetServer()
+ if svr != nil && cmdIDExist {
+ svr.CommandDelete(cmdIDData.(string))
+ } else {
+ s.Log.Infof("%s: cannot retrieve server for sid=%s, prjID=%s, evD=%v", evN, sid, prjID, evD)
+ }
+ } else {
+ s.Log.Infof("%s: cannot retrieve project for sid=%s, prjID=%s", evN, sid, prjID)
+ }
+
// cleanup listener
- for i, evName := range evtList {
+ for i, evName := range evtOutList {
svr.EventOff(evName, fwdFuncID[i])
}
svr.EventOff(evN, exitFuncID)
return nil
}
- exitFuncID, err = svr.EventOn(apiv1.ExecExitEvent, sess.ID, exitFunc)
+
+ prjCfg := (*prj).GetProject()
+ privData := map[string]string{"sessID": sess.ID, "prjID": prjCfg.ID}
+ exitFuncID, err = svr.EventOn(xaapiv1.ExecExitEvent, privData, exitFunc)
if err != nil {
common.APIError(c, err.Error())
return
}
// Forward back command to right server
- response, err := svr.SendCommand(cmd, data)
- if err != nil {
+ res := xsapiv1.ExecResult{}
+ xsArgs := &xsapiv1.ExecArgs{
+ ID: args.ID,
+ SdkID: args.SdkID,
+ CmdID: args.CmdID,
+ Cmd: args.Cmd,
+ Args: args.Args,
+ Env: args.Env,
+ RPath: args.RPath,
+ TTY: args.TTY,
+ TTYGdbserverFix: args.TTYGdbserverFix,
+ ExitImmediate: args.ExitImmediate,
+ CmdTimeout: args.CmdTimeout,
+ }
+ if err := svr.CommandExec(xsArgs, &res); 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")
+ // Add command to running commands list
+ if err := svr.CommandAdd(res.CmdID, xsArgs); err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ c.JSON(http.StatusOK, xaapiv1.ExecResult{Status: res.Status, CmdID: res.CmdID})
+}
+
+// execSignalCmd executes remotely the signal command
+func (s *APIService) execSignalCmd(c *gin.Context) {
+
+ args := xaapiv1.ExecSignalArgs{}
+ if err := c.BindJSON(&args); err != nil {
+ s.Log.Warningf("/signal invalid args, err=%v", err)
+ common.APIError(c, "Invalid arguments")
return
}
- c.JSON(http.StatusOK, string(body))
+
+ // Retrieve on which xds-server the command is running
+ var svr *XdsServer
+ var dataCmd interface{}
+ for _, svr = range s.xdsServers {
+ dataCmd = svr.CommandGet(args.CmdID)
+ if dataCmd != nil {
+ break
+ }
+ }
+ if dataCmd == nil {
+ common.APIError(c, "Cannot retrieve XDS Server for this cmdID")
+ return
+ }
+
+ // Forward back command to right server
+ res := xsapiv1.ExecSigResult{}
+ xsArgs := &xsapiv1.ExecSignalArgs{
+ CmdID: args.CmdID,
+ Signal: args.Signal,
+ }
+ if err := svr.CommandSignal(xsArgs, &res); err != nil {
+ common.APIError(c, err.Error())
+ return
+ }
+
+ c.JSON(http.StatusOK, xaapiv1.ExecSignalResult{Status: res.Status, CmdID: res.CmdID})
}