2 * Copyright (C) 2017-2018 "IoT.bzh"
3 * Author Sebastien Douheret <sebastien@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
26 "gerrit.automotivelinux.org/gerrit/src/xds/xds-agent.git/lib/xaapiv1"
27 "github.com/urfave/cli"
30 func initCmdExec(cmdDef *[]cli.Command) {
31 *cmdDef = append(*cmdDef, cli.Command{
33 Usage: "execute a command in XDS",
38 EnvVar: "XDS_PROJECT_ID",
39 Usage: "project ID you want to build (mandatory variable)",
44 Usage: "relative path into project",
49 Usage: "Cross Sdk ID to use to build project",
52 Name: "ldlibpath-no-reset",
54 EnvVar: "XDS_LD_LIBRARY_PATH_NO_RESET",
55 Usage: "Don't reset LD_LIBRARY_PATH before executing command",
61 func execCmd(ctx *cli.Context) error {
62 prjID := ctx.String("id")
63 rPath := ctx.String("rpath")
64 sdkid := ctx.String("sdkid")
66 // Check mandatory args
68 return cli.NewExitError("project id must be set (see --id option)", 1)
71 argsCommand := make([]string, len(ctx.Args()))
72 copy(argsCommand, ctx.Args())
73 Log.Infof("Execute: /exec %v", argsCommand)
75 // Log useful info for debugging
76 ver := xaapiv1.XDSVersion{}
78 Log.Infof("XDS version: %v", ver)
80 // Process Socket IO events
81 type exitResult struct {
85 exitChan := make(chan exitResult, 1)
87 IOSkClient.On("disconnection", func(err error) {
88 Log.Debugf("WS disconnection event with err: %v\n", err)
89 exitChan <- exitResult{err, 2}
92 outFunc := func(timestamp, stdout, stderr string) {
94 if ctx.Bool("WithTimestamp") {
98 fmt.Printf("%s%s", tm, stdout)
101 fmt.Fprintf(os.Stderr, "%s%s", tm, stderr)
105 IOSkClient.On(xaapiv1.ExecOutEvent, func(ev xaapiv1.ExecOutMsg) {
106 outFunc(ev.Timestamp, ev.Stdout, ev.Stderr)
109 IOSkClient.On(xaapiv1.ExecExitEvent, func(ev xaapiv1.ExecExitMsg) {
110 exitChan <- exitResult{ev.Error, ev.Code}
113 IOSkClient.On(xaapiv1.EVTProjectChange, func(ev xaapiv1.EventMsg) {
114 prj, _ := ev.DecodeProjectConfig()
115 Log.Infof("Event %v (%v): %v", ev.Type, ev.Time, prj)
117 evReg := xaapiv1.EventRegisterArgs{Name: xaapiv1.EVTProjectChange}
118 if err := HTTPCli.Post("/events/register", &evReg, nil); err != nil {
119 return cli.NewExitError(err, 1)
122 // Retrieve the project definition
123 prj := xaapiv1.ProjectConfig{}
124 if err := HTTPCli.Get("/projects/"+prjID, &prj); err != nil {
125 return cli.NewExitError(err, 1)
128 // Auto setup rPath if needed
130 cwd, err := os.Getwd()
132 fldRp := prj.ClientPath
133 if !strings.HasPrefix(fldRp, "/") {
136 Log.Debugf("Try to auto-setup rPath: cwd=%s ; ClientPath=%s", cwd, fldRp)
137 if sp := strings.SplitAfter(cwd, fldRp); len(sp) == 2 {
138 rPath = strings.Trim(sp[1], "/")
139 Log.Debugf("Auto-setup rPath to: '%s'", rPath)
145 Log.Debugf("Command env: %v", EnvConfFileMap)
147 for k, v := range EnvConfFileMap {
148 env = append(env, k+"="+v)
151 // Send build command
152 args := xaapiv1.ExecArgs{
155 Cmd: strings.Trim(argsCommand[0], " "),
156 Args: argsCommand[1:],
159 LdLibPathNoReset: ctx.Bool("ldlibpath-no-reset"),
163 LogPost("POST /exec %v", args)
164 if err := HTTPCli.Post("/exec", args, nil); err != nil {
165 return cli.NewExitError(err.Error(), 1)
170 case res := <-IOSkClient.ServerDiscoChan:
171 Log.Debugf("XDS Server disconnected %v", res)
172 return cli.NewExitError(res.error, res.code)
174 case res := <-exitChan:
177 Log.Debugln("Exit successfully")
179 if res.error != nil {
180 Log.Debugln("Exit with ERROR: ", res.error.Error())
181 errStr = res.error.Error()
183 return cli.NewExitError(errStr, res.code)