Add SDKs support.
[src/xds/xds-server.git] / lib / apiv1 / make.go
1 package apiv1
2
3 import (
4         "net/http"
5
6         "time"
7
8         "strconv"
9
10         "github.com/gin-gonic/gin"
11         "github.com/iotbzh/xds-server/lib/common"
12 )
13
14 // MakeArgs is the parameters (json format) of /make command
15 type MakeArgs struct {
16         ID         string `json:"id"`
17         RPath      string `json:"rpath"` // relative path into project
18         Args       string `json:"args"`
19         CmdTimeout int    `json:"timeout"` // command completion timeout in Second
20 }
21
22 // MakeOutMsg Message send on each output (stdout+stderr) of make command
23 type MakeOutMsg struct {
24         CmdID     string `json:"cmdID"`
25         Timestamp string `json:"timestamp"`
26         Stdout    string `json:"stdout"`
27         Stderr    string `json:"stderr"`
28 }
29
30 // MakeExitMsg Message send on make command exit
31 type MakeExitMsg struct {
32         CmdID     string `json:"cmdID"`
33         Timestamp string `json:"timestamp"`
34         Code      int    `json:"code"`
35         Error     error  `json:"error"`
36 }
37
38 // MakeOutEvent Event send in WS when characters are received on stdout/stderr
39 const MakeOutEvent = "make:output"
40
41 // MakeExitEvent Event send in WS when command exited
42 const MakeExitEvent = "make:exit"
43
44 var makeCommandID = 1
45
46 func (s *APIService) buildMake(c *gin.Context) {
47         var args MakeArgs
48
49         if c.BindJSON(&args) != nil {
50                 common.APIError(c, "Invalid arguments")
51                 return
52         }
53
54         sess := s.sessions.Get(c)
55         if sess == nil {
56                 common.APIError(c, "Unknown sessions")
57                 return
58         }
59         sop := sess.IOSocket
60         if sop == nil {
61                 common.APIError(c, "Websocket not established")
62                 return
63         }
64
65         // Allow to pass id in url (/make/:id) or as JSON argument
66         id := c.Param("id")
67         if id == "" {
68                 id = args.ID
69         }
70         if id == "" {
71                 common.APIError(c, "Invalid id")
72                 return
73         }
74
75         prj := s.mfolder.GetFolderFromID(id)
76         if prj == nil {
77                 common.APIError(c, "Unknown id")
78                 return
79         }
80
81         execTmo := args.CmdTimeout
82         if execTmo == 0 {
83                 // TODO get default timeout from config.json file
84                 execTmo = 24 * 60 * 60 // 1 day
85         }
86
87         cmd := "cd " + prj.GetFullPath(args.RPath) + " && make"
88         if args.Args != "" {
89                 cmd += " " + args.Args
90         }
91
92         // Define callback for output
93         var oCB common.EmitOutputCB
94         oCB = func(sid string, id int, stdout, stderr string) {
95                 // IO socket can be nil when disconnected
96                 so := s.sessions.IOSocketGet(sid)
97                 if so == nil {
98                         s.log.Infof("%s not emitted: WS closed - sid: %s - msg id:%d", MakeOutEvent, sid, id)
99                         return
100                 }
101                 s.log.Debugf("%s emitted - WS sid %s - id:%d", MakeOutEvent, sid, id)
102
103                 // FIXME replace by .BroadcastTo a room
104                 err := (*so).Emit(MakeOutEvent, MakeOutMsg{
105                         CmdID:     strconv.Itoa(id),
106                         Timestamp: time.Now().String(),
107                         Stdout:    stdout,
108                         Stderr:    stderr,
109                 })
110                 if err != nil {
111                         s.log.Errorf("WS Emit : %v", err)
112                 }
113         }
114
115         // Define callback for output
116         eCB := func(sid string, id int, code int, err error) {
117                 s.log.Debugf("Command [Cmd ID %d] exited: code %d, error: %v", id, code, err)
118
119                 // IO socket can be nil when disconnected
120                 so := s.sessions.IOSocketGet(sid)
121                 if so == nil {
122                         s.log.Infof("%s not emitted - WS closed (id:%d", MakeExitEvent, id)
123                         return
124                 }
125
126                 // FIXME replace by .BroadcastTo a room
127                 e := (*so).Emit(MakeExitEvent, MakeExitMsg{
128                         CmdID:     strconv.Itoa(id),
129                         Timestamp: time.Now().String(),
130                         Code:      code,
131                         Error:     err,
132                 })
133                 if e != nil {
134                         s.log.Errorf("WS Emit : %v", e)
135                 }
136         }
137
138         cmdID := makeCommandID
139         makeCommandID++
140
141         /* SEB TODO . /opt/poky-agl/3.90.0+snapshot/environment-setup-aarch64-agl-linux
142         env := os.Environ()
143         */
144
145         s.log.Debugf("Execute [Cmd ID %d]: %v", cmdID, cmd)
146         err := common.ExecPipeWs(cmd, sop, sess.ID, cmdID, execTmo, s.log, oCB, eCB)
147         if err != nil {
148                 common.APIError(c, err.Error())
149                 return
150         }
151
152         c.JSON(http.StatusOK,
153                 gin.H{
154                         "status": "OK",
155                         "cmdID":  cmdID,
156                 })
157 }