aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastien Douheret <sebastien.douheret@iot.bzh>2017-07-09 15:43:18 +0200
committerSebastien Douheret <sebastien.douheret@iot.bzh>2017-08-07 18:55:36 +0200
commitbf2487c4e4c925f437f9e72f09f6ef5099a0c3cb (patch)
treea7d543069aaf1f557baa5c02d0125f7fd61770f4
parente9b18cd409f82928e1c4de3029ee1cc2d3816552 (diff)
Add stdin support to /exec
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
-rw-r--r--lib/apiv1/apiv1.go1
-rw-r--r--lib/apiv1/exec.go61
-rw-r--r--lib/apiv1/make.go16
3 files changed, 63 insertions, 15 deletions
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{}