8 "github.com/iotbzh/xds-agent/lib/apiv1"
9 common "github.com/iotbzh/xds-common/golib"
10 "github.com/joho/godotenv"
11 "github.com/urfave/cli"
14 func initCmdExec(cmdDef *[]cli.Command) {
15 *cmdDef = append(*cmdDef, cli.Command{
17 Usage: "execute a command in XDS",
22 EnvVar: "XDS_PROJECT_ID",
23 Usage: "project ID you want to build (mandatory variable)",
28 Usage: "relative path into project",
33 Usage: "Cross Sdk ID to use to build project",
39 func exec(ctx *cli.Context) error {
40 prjID := ctx.String("id")
41 confFile := ctx.String("config")
42 rPath := ctx.String("rPath")
43 sdkid := ctx.String("sdkid")
45 // Check mandatory args
47 return cli.NewExitError("project id must be set (see --id option)", 1)
50 // Load config file if requested
51 envMap := make(map[string]string)
53 if !common.Exists(confFile) {
54 exitError(1, "Error env config file not found")
56 // Load config file variables that will overwrite env variables
57 err := godotenv.Overload(confFile)
59 exitError(1, "Error loading env config file "+confFile)
61 envMap, err = godotenv.Read(confFile)
63 exitError(1, "Error reading env config file "+confFile)
67 argsCommand := make([]string, len(ctx.Args()))
68 copy(argsCommand, ctx.Args())
69 Log.Infof("Execute: /exec %v", argsCommand)
71 // Log useful info for debugging
72 ver := apiv1.XDSVersion{}
74 Log.Infof("XDS version: %v", ver)
76 // Process Socket IO events
77 type exitResult struct {
81 exitChan := make(chan exitResult, 1)
83 IOsk.On("disconnection", func(err error) {
84 exitChan <- exitResult{err, 2}
87 outFunc := func(timestamp, stdout, stderr string) {
89 if ctx.Bool("WithTimestamp") {
93 fmt.Printf("%s%s", tm, stdout)
96 fmt.Fprintf(os.Stderr, "%s%s", tm, stderr)
100 IOsk.On(apiv1.ExecOutEvent, func(ev apiv1.ExecOutMsg) {
101 outFunc(ev.Timestamp, ev.Stdout, ev.Stderr)
104 IOsk.On(apiv1.ExecExitEvent, func(ev apiv1.ExecExitMsg) {
105 exitChan <- exitResult{ev.Error, ev.Code}
108 // Retrieve the project definition
109 prj := apiv1.ProjectConfig{}
110 if err := HTTPCli.Get("/projects/"+prjID, &prj); err != nil {
111 return cli.NewExitError(err, 1)
114 // Auto setup rPath if needed
116 cwd, err := os.Getwd()
118 fldRp := prj.ClientPath
119 if !strings.HasPrefix(fldRp, "/") {
122 Log.Debugf("Try to auto-setup rPath: cwd=%s ; ClientPath=%s", cwd, fldRp)
123 if sp := strings.SplitAfter(cwd, fldRp); len(sp) == 2 {
124 rPath = strings.Trim(sp[1], "/")
125 Log.Debugf("Auto-setup rPath to: '%s'", rPath)
131 Log.Debugf("Command env: %v", envMap)
133 for k, v := range envMap {
134 env = append(env, k+"="+v)
137 // Send build command
138 args := apiv1.ExecArgs{
141 Cmd: strings.Trim(argsCommand[0], " "),
142 Args: argsCommand[1:],
148 LogPost("POST /exec %v", args)
149 if err := HTTPCli.Post("/exec", args, nil); err != nil {
150 return cli.NewExitError(err.Error(), 1)
155 case res := <-exitChan:
158 Log.Debugln("Exit successfully")
160 if res.error != nil {
161 Log.Debugln("Exit with ERROR: ", res.error.Error())
162 errStr = res.error.Error()
164 return cli.NewExitError(errStr, res.code)