Refit source files to have a public xs-apiv1 lib package.
[src/xds/xds-server.git] / lib / xdsserver / apiv1-make.go
1 package xdsserver
2
3 import (
4         "github.com/gin-gonic/gin"
5         common "github.com/iotbzh/xds-common/golib"
6 )
7
8 /* TODO: Deprecated - should be removed
9 // MakeArgs is the parameters (json format) of /make command
10 type MakeArgs struct {
11         ID            string   `json:"id"`
12         SdkID         string   `json:"sdkID"` // sdk ID to use for setting env
13         CmdID         string   `json:"cmdID"` // command unique ID
14         Args          []string `json:"args"`  // args to pass to make command
15         Env           []string `json:"env"`
16         RPath         string   `json:"rpath"`         // relative path into project
17         ExitImmediate bool     `json:"exitImmediate"` // when true, exit event sent immediately when command exited (IOW, don't wait file synchronization)
18         CmdTimeout    int      `json:"timeout"`       // command completion timeout in Second
19 }
20
21 // MakeOutMsg Message send on each output (stdout+stderr) of make command
22 type MakeOutMsg struct {
23         CmdID     string `json:"cmdID"`
24         Timestamp string `json:"timestamp"`
25         Stdout    string `json:"stdout"`
26         Stderr    string `json:"stderr"`
27 }
28
29 // MakeExitMsg Message send on make command exit
30 type MakeExitMsg struct {
31         CmdID     string `json:"cmdID"`
32         Timestamp string `json:"timestamp"`
33         Code      int    `json:"code"`
34         Error     error  `json:"error"`
35 }
36
37 // MakeOutEvent Event send in WS when characters are received on stdout/stderr
38 const MakeOutEvent = "make:output"
39
40 // MakeExitEvent Event send in WS when command exited
41 const MakeExitEvent = "make:exit"
42
43 var makeCommandID = 1
44 */
45
46 func (s *APIService) buildMake(c *gin.Context) {
47         common.APIError(c, "/make route is not longer supported, use /exec instead")
48
49         /*
50                 var args MakeArgs
51
52                 if c.BindJSON(&args) != nil {
53                         common.APIError(c, "Invalid arguments")
54                         return
55                 }
56
57                 sess := s.sessions.Get(c)
58                 if sess == nil {
59                         common.APIError(c, "Unknown sessions")
60                         return
61                 }
62                 sop := sess.IOSocket
63                 if sop == nil {
64                         common.APIError(c, "Websocket not established")
65                         return
66                 }
67
68                 // Allow to pass id in url (/make/:id) or as JSON argument
69                 idArg := c.Param("id")
70                 if idArg == "" {
71                         idArg = args.ID
72                 }
73                 if idArg == "" {
74                         common.APIError(c, "Invalid id")
75                         return
76                 }
77                 id, err := s.mfolders.ResolveID(idArg)
78                 if err != nil {
79                         common.APIError(c, err.Error())
80                         return
81                 }
82                 pf := s.mfolders.Get(id)
83                 if pf == nil {
84                         common.APIError(c, "Unknown id")
85                         return
86                 }
87                 folder := *pf
88                 prj := folder.GetConfig()
89
90                 execTmo := args.CmdTimeout
91                 if execTmo == 0 {
92                         // TODO get default timeout from config.json file
93                         execTmo = 24 * 60 * 60 // 1 day
94                 }
95
96                 // TODO merge all code below with exec.go
97
98                 // Define callback for output
99                 var oCB common.EmitOutputCB
100                 oCB = func(sid string, cmdID string, stdout, stderr string, data *map[string]interface{}) {
101                         // IO socket can be nil when disconnected
102                         so := s.sessions.IOSocketGet(sid)
103                         if so == nil {
104                                 s.log.Infof("%s not emitted: WS closed - sid: %s - msg id:%s", MakeOutEvent, sid, cmdID)
105                                 return
106                         }
107
108                         // Retrieve project ID and RootPath
109                         prjID := (*data)["ID"].(string)
110                         prjRootPath := (*data)["RootPath"].(string)
111
112                         // Cleanup any references to internal rootpath in stdout & stderr
113                         stdout = strings.Replace(stdout, prjRootPath, "", -1)
114                         stderr = strings.Replace(stderr, prjRootPath, "", -1)
115
116                         s.log.Debugf("%s emitted - WS sid %s - id:%d - prjID:%s", MakeOutEvent, sid, id, prjID)
117
118                         // FIXME replace by .BroadcastTo a room
119                         err := (*so).Emit(MakeOutEvent, MakeOutMsg{
120                                 CmdID:     cmdID,
121                                 Timestamp: time.Now().String(),
122                                 Stdout:    stdout,
123                                 Stderr:    stderr,
124                         })
125                         if err != nil {
126                                 s.log.Errorf("WS Emit : %v", err)
127                         }
128                 }
129
130                 // Define callback for output
131                 eCB := func(sid string, cmdID string, code int, err error, data *map[string]interface{}) {
132                         s.log.Debugf("Command [Cmd ID %s] exited: code %d, error: %v", cmdID, code, err)
133
134                         // IO socket can be nil when disconnected
135                         so := s.sessions.IOSocketGet(sid)
136                         if so == nil {
137                                 s.log.Infof("%s not emitted - WS closed (id:%s", MakeExitEvent, cmdID)
138                                 return
139                         }
140
141                         // Retrieve project ID and RootPath
142                         prjID := (*data)["ID"].(string)
143                         exitImm := (*data)["ExitImmediate"].(bool)
144
145                         // XXX - workaround to be sure that Syncthing detected all changes
146                         if err := s.mfolders.ForceSync(prjID); err != nil {
147                                 s.log.Errorf("Error while syncing folder %s: %v", prjID, err)
148                         }
149                         if !exitImm {
150                                 // Wait end of file sync
151                                 // FIXME pass as argument
152                                 tmo := 60
153                                 for t := tmo; t > 0; t-- {
154                                         s.log.Debugf("Wait file insync for %s (%d/%d)", prjID, t, tmo)
155                                         if sync, err := s.mfolders.IsFolderInSync(prjID); sync || err != nil {
156                                                 if err != nil {
157                                                         s.log.Errorf("ERROR IsFolderInSync (%s): %v", prjID, err)
158                                                 }
159                                                 break
160                                         }
161                                         time.Sleep(time.Second)
162                                 }
163                         }
164
165                         // FIXME replace by .BroadcastTo a room
166                         e := (*so).Emit(MakeExitEvent, MakeExitMsg{
167                                 CmdID:     id,
168                                 Timestamp: time.Now().String(),
169                                 Code:      code,
170                                 Error:     err,
171                         })
172                         if e != nil {
173                                 s.log.Errorf("WS Emit : %v", e)
174                         }
175                 }
176
177                 // Unique ID for each commands
178                 if args.CmdID == "" {
179                         args.CmdID = s.cfg.ServerUID[:18] + "_" + strconv.Itoa(makeCommandID)
180                         makeCommandID++
181                 }
182                 cmd := []string{}
183
184                 // Retrieve env command regarding Sdk ID
185                 if envCmd := s.sdks.GetEnvCmd(args.SdkID, prj.DefaultSdk); len(envCmd) > 0 {
186                         cmd = append(cmd, envCmd...)
187                         cmd = append(cmd, "&&")
188                 }
189
190                 cmd = append(cmd, "cd", folder.GetFullPath(args.RPath), "&&", "make")
191                 if len(args.Args) > 0 {
192                         cmd = append(cmd, args.Args...)
193                 }
194
195                 s.log.Debugf("Execute [Cmd ID %d]: %v", args.CmdID, cmd)
196
197                 data := make(map[string]interface{})
198                 data["ID"] = prj.ID
199                 data["RootPath"] = prj.RootPath
200                 data["ExitImmediate"] = args.ExitImmediate
201
202                 err = common.ExecPipeWs(cmd, args.Env, sop, sess.ID, args.CmdID, execTmo, s.log, oCB, eCB, &data)
203                 if err != nil {
204                         common.APIError(c, err.Error())
205                         return
206                 }
207
208                 c.JSON(http.StatusOK,
209                         gin.H{
210                                 "status": "OK",
211                                 "cmdID":  args.CmdID,
212                         })
213         */
214 }