summaryrefslogtreecommitdiffstats
path: root/dab_4.0.2.xml
blob: 1694d19746edf7e5361d0a7c76a174daa41acd94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package apiv1

import (
	"net/http"

	"time"

	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/iotbzh/xds-server/lib/common"
)

// MakeArgs is the parameters (json format) of /make command
type MakeArgs struct {
	ID         string `json:"id"`
	RPath      string `json:"rpath"` // relative path into project
	Args       string `json:"args"`
	CmdTimeout int    `json:"timeout"` // command completion timeout in Second
}

// MakeOutMsg Message send on each output (stdout+stderr) of make command
type MakeOutMsg struct {
	CmdID     string `json:"cmdID"`
	Timestamp string `json:"timestamp"`
	Stdout    string `json:"stdout"`
	Stderr    string `json:"stderr"`
}

// MakeExitMsg Message send on make command exit
type MakeExitMsg struct {
	CmdID     string `json:"cmdID"`
	Timestamp string `json:"timestamp"`
	Code      int    `json:"code"`
	Error     error  `json:"error"`
}

// MakeOutEvent Event send in WS when characters are received on stdout/stderr
const MakeOutEvent = "make:output"

// MakeExitEvent Event send in WS when command exited
const MakeExitEvent = "make:exit"

var makeCommandID = 1

func (s *APIService) buildMake(c *gin.Context) {
	var args MakeArgs

	if c.BindJSON(&args) != nil {
		common.APIError(c, "Invalid arguments")
		return
	}

	sess := s.sessions.Get(c)
	if sess == nil {
		common.APIError(c, "Unknown sessions")
		return
	}
	sop := sess.IOSocket
	if sop == nil {
		common.APIError(c, "Websocket not established")
		return
	}

	// Allow to pass id in url (/make/:id) or as JSON argument
	id := c.Param("id")
	if id == "" {
		id = args.ID
	}
	if id == "" {
		common.APIError(c, "Invalid id")
		return
	}

	prj := s.mfolder.GetFolderFromID(id)
	if prj == nil {
		common.APIError(c, "Unknown id")
		return
	}

	execTmo := args.CmdTimeout
	if execTmo == 0 {
		// TODO get default timeout from config.json file
		execTmo = 24 * 60 * 60 // 1 day
	}

	cmd := "cd " + prj.GetFullPath(args.RPath) + " && make"
	if args.Args != "" {
		cmd += " " + args.Args
	}

	// Define callback for output
	var oCB common.EmitOutputCB
	oCB = func(sid string, id int, stdout, stderr string) {
		// 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)
			return
		}
		s.log.Debugf("%s emitted - WS sid %s - id:%d", MakeOutEvent, sid, id)

		// FIXME replace by .BroadcastTo a room
		err := (*so).
x">Stderr: stderr, }) if err != nil { s.log.Errorf("WS Emit : %v", err) } } // Define callback for output eCB := func(sid string, id int, code int, err error) { s.log.Debugf("Command [Cmd ID %d] exited: code %d, error: %v", id, 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) return } // FIXME replace by .BroadcastTo a room e := (*so).Emit(MakeExitEvent, MakeExitMsg{ CmdID: strconv.Itoa(id), Timestamp: time.Now().String(), Code: code, Error: err, }) if e != nil { s.log.Errorf("WS Emit : %v", e) } } cmdID := makeCommandID makeCommandID++ s.log.Debugf("Execute [Cmd ID %d]: %v", cmdID, cmd) err := common.ExecPipeWs(cmd, sop, sess.ID, cmdID, execTmo, s.log, oCB, eCB) if err != nil { common.APIError(c, err.Error()) return } c.JSON(http.StatusOK, gin.H{ "status": "OK", "cmdID": cmdID, }) }