From: Sebastien Douheret Date: Sun, 9 Jul 2017 13:43:18 +0000 (+0200) Subject: Add stdin support to /exec X-Git-Tag: v0.2.0-beta~1^2~15 X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=commitdiff_plain;h=bf2487c4e4c925f437f9e72f09f6ef5099a0c3cb;p=src%2Fxds%2Fxds-server.git Add stdin support to /exec Signed-off-by: Sebastien Douheret --- diff --git a/lib/apiv1/apiv1.go b/lib/apiv1/apiv1.go index 7fa69e9..cde2526 100644 --- a/lib/apiv1/apiv1.go +++ b/lib/apiv1/apiv1.go @@ -52,6 +52,7 @@ func New(r *gin.Engine, sess *session.Sessions, cfg *xdsconfig.Config, mfolder * s.apiRouter.POST("/exec", s.execCmd) s.apiRouter.POST("/exec/:id", s.execCmd) + s.apiRouter.POST("/signal", s.execSignalCmd) return s } diff --git a/lib/apiv1/exec.go b/lib/apiv1/exec.go index 6c70a98..ce0241a 100644 --- a/lib/apiv1/exec.go +++ b/lib/apiv1/exec.go @@ -6,6 +6,8 @@ import ( "strings" "time" + "fmt" + "github.com/gin-gonic/gin" common "github.com/iotbzh/xds-common/golib" ) @@ -38,6 +40,12 @@ type ExecExitMsg struct { Error error `json:"error"` } +// ExecSignalArgs JSON parameters of /exec/signal command +type ExecSignalArgs struct { + CmdID string `json:"cmdID" binding:"required"` // command id + Signal string `json:"signal" binding:"required"` // signal number +} + // ExecOutEvent Event send in WS when characters are received const ExecOutEvent = "exec:output" @@ -85,14 +93,26 @@ func (s *APIService) execCmd(c *gin.Context) { } execTmo := args.CmdTimeout - if execTmo == 0 { + if execTmo == -1 { + // -1 : no timeout + execTmo = 365 * 24 * 60 * 60 // 1 year == no timeout + } else if execTmo == 0 { + // 0 : default timeout // TODO get default timeout from config.json file execTmo = 24 * 60 * 60 // 1 day } + // Define callback for input + /* SEB TODO + var iCB common.OnInputCB + iCB = func() { + + } + */ + // Define callback for output var oCB common.EmitOutputCB - oCB = func(sid string, id int, stdout, stderr string, data *map[string]interface{}) { + oCB = func(sid string, id string, stdout, stderr string, data *map[string]interface{}) { // IO socket can be nil when disconnected so := s.sessions.IOSocketGet(sid) if so == nil { @@ -110,9 +130,11 @@ func (s *APIService) execCmd(c *gin.Context) { s.log.Debugf("%s emitted - WS sid %s - id:%d - prjID:%s", ExecOutEvent, sid, id, prjID) + fmt.Printf("SEB SEND out <%v>, err <%v>\n", stdout, stderr) + // FIXME replace by .BroadcastTo a room err := (*so).Emit(ExecOutEvent, ExecOutMsg{ - CmdID: strconv.Itoa(id), + CmdID: id, Timestamp: time.Now().String(), Stdout: stdout, Stderr: stderr, @@ -123,7 +145,7 @@ func (s *APIService) execCmd(c *gin.Context) { } // Define callback for output - eCB := func(sid string, id int, code int, err error, data *map[string]interface{}) { + eCB := func(sid string, id string, code int, err error, data *map[string]interface{}) { s.log.Debugf("Command [Cmd ID %d] exited: code %d, error: %v", id, code, err) // IO socket can be nil when disconnected @@ -159,7 +181,7 @@ func (s *APIService) execCmd(c *gin.Context) { // FIXME replace by .BroadcastTo a room e := (*so).Emit(ExecExitEvent, ExecExitMsg{ - CmdID: strconv.Itoa(id), + CmdID: id, Timestamp: time.Now().String(), Code: code, Error: err, @@ -169,7 +191,7 @@ func (s *APIService) execCmd(c *gin.Context) { } } - cmdID := execCommandID + cmdID := strconv.Itoa(execCommandID) execCommandID++ cmd := []string{} @@ -190,10 +212,13 @@ func (s *APIService) execCmd(c *gin.Context) { cmd = append(cmd, args.Args...) } + // SEB Workaround for stderr issue (order not respected with stdout) + cmd = append(cmd, " 2>&1") + // Append client project dir to environment args.Env = append(args.Env, "CLIENT_PROJECT_DIR="+prj.RelativePath) - s.log.Debugf("Execute [Cmd ID %d]: %v", cmdID, cmd) + s.log.Debugf("Execute [Cmd ID %s]: %v", cmdID, cmd) data := make(map[string]interface{}) data["ID"] = prj.ID @@ -212,3 +237,25 @@ func (s *APIService) execCmd(c *gin.Context) { "cmdID": cmdID, }) } + +// ExecCmd executes remotely a command +func (s *APIService) execSignalCmd(c *gin.Context) { + var args ExecSignalArgs + + if c.BindJSON(&args) != nil { + common.APIError(c, "Invalid arguments") + return + } + + s.log.Debugf("Signal %s for command ID %s", args.Signal, args.CmdID) + err := common.ExecSignal(args.CmdID, args.Signal) + if err != nil { + common.APIError(c, err.Error()) + return + } + + c.JSON(http.StatusOK, + gin.H{ + "status": "OK", + }) +} diff --git a/lib/apiv1/make.go b/lib/apiv1/make.go index 5cd98c6..6ae840b 100644 --- a/lib/apiv1/make.go +++ b/lib/apiv1/make.go @@ -92,11 +92,11 @@ func (s *APIService) buildMake(c *gin.Context) { // Define callback for output var oCB common.EmitOutputCB - oCB = func(sid string, id int, stdout, stderr string, data *map[string]interface{}) { + oCB = func(sid string, cmdID string, stdout, stderr string, data *map[string]interface{}) { // IO socket can be nil when disconnected so := s.sessions.IOSocketGet(sid) if so == nil { - s.log.Infof("%s not emitted: WS closed - sid: %s - msg id:%d", MakeOutEvent, sid, id) + s.log.Infof("%s not emitted: WS closed - sid: %s - msg id:%s", MakeOutEvent, sid, cmdID) return } @@ -112,7 +112,7 @@ func (s *APIService) buildMake(c *gin.Context) { // FIXME replace by .BroadcastTo a room err := (*so).Emit(MakeOutEvent, MakeOutMsg{ - CmdID: strconv.Itoa(id), + CmdID: cmdID, Timestamp: time.Now().String(), Stdout: stdout, Stderr: stderr, @@ -123,13 +123,13 @@ func (s *APIService) buildMake(c *gin.Context) { } // Define callback for output - eCB := func(sid string, id int, code int, err error, data *map[string]interface{}) { - s.log.Debugf("Command [Cmd ID %d] exited: code %d, error: %v", id, code, err) + eCB := func(sid string, cmdID string, code int, err error, data *map[string]interface{}) { + s.log.Debugf("Command [Cmd ID %s] exited: code %d, error: %v", cmdID, code, err) // IO socket can be nil when disconnected so := s.sessions.IOSocketGet(sid) if so == nil { - s.log.Infof("%s not emitted - WS closed (id:%d", MakeExitEvent, id) + s.log.Infof("%s not emitted - WS closed (id:%s", MakeExitEvent, cmdID) return } @@ -159,7 +159,7 @@ func (s *APIService) buildMake(c *gin.Context) { // FIXME replace by .BroadcastTo a room e := (*so).Emit(MakeExitEvent, MakeExitMsg{ - CmdID: strconv.Itoa(id), + CmdID: id, Timestamp: time.Now().String(), Code: code, Error: err, @@ -169,7 +169,7 @@ func (s *APIService) buildMake(c *gin.Context) { } } - cmdID := makeCommandID + cmdID := strconv.Itoa(makeCommandID) makeCommandID++ cmd := []string{}