11package command
22
33import (
4+ "bytes"
45 "coscale/api"
6+ "errors"
57 "flag"
68 "fmt"
79 "io"
810 "os"
11+ "os/exec"
912 "path/filepath"
13+ "runtime"
1014 "strings"
1115 "text/template"
16+ "time"
1217 "unicode"
1318 "unicode/utf8"
1419)
@@ -102,14 +107,14 @@ func (c *Command) PrintUsage() {
102107 os .Exit (2 )
103108}
104109
105- //return a Api object
110+ // GetApi returns a Api object
106111func (c * Command ) GetApi (baseUrl , accessToken , appId string , rawOutput bool ) * api.Api {
107112 if accessToken == "" || appId == "" {
108- dir , err := filepath . Abs ( filepath . Dir ( os . Args [ 0 ]) )
113+ configPath , err := GetConfigPath ( )
109114 if err != nil {
110115 os .Exit (EXIT_FLAG_ERROR )
111116 }
112- config , err := api .ReadApiConfiguration (dir + "/api.conf" )
117+ config , err := api .ReadApiConfiguration (configPath )
113118 if err != nil {
114119 c .PrintUsage ()
115120 }
@@ -142,26 +147,27 @@ func (c *Command) ParseArgs(args []string) {
142147
143148func (c * Command ) PrintResult (result string , err error ) {
144149 if err == nil {
145- fmt .Fprint (os .Stdout , result )
150+ fmt .Fprintln (os .Stdout , result )
146151 os .Exit (EXIT_SUCCESS )
147152 } else if api .IsAuthenticationError (err ) {
148- fmt .Fprint (os .Stderr , `{"msg":"Authentication failed!"}` )
153+ fmt .Fprintln (os .Stderr , `{"msg":"Authentication failed!"}` )
149154 os .Exit (EXIT_AUTHENTICATION_ERROR )
150155 } else {
151- fmt .Fprintf (os .Stderr , GetErrorJson (err ))
156+ fmt .Fprintln (os .Stderr , GetErrorJson (err ))
152157 os .Exit (EXIT_SUCCESS_ERROR )
153158 }
154159}
155160
156161// GetErrorJson return only the json string from a error message from api
157162func GetErrorJson (err error ) string {
158- if strings .Index (err .Error (), `{` ) > - 1 {
163+ index := strings .Index (err .Error (), `{` )
164+ if index > - 1 {
159165 return err .Error ()[strings .Index (err .Error (), `{` ):]
160166 }
161- return err .Error ()
167+ return fmt . Sprintf ( `{"msg":"%s"}` , err .Error () )
162168}
163169
164- var usageTemplate = `cli-cmd a tool for CoScale Api.
170+ var usageTemplate = `coscale-cli a tool for CoScale Api.
165171
166172Usage:
167173 {{.UsageLine}}
@@ -178,16 +184,68 @@ Usage:
178184The json objects are returned formatted by default, but can be returned on 1 line by using:
179185 --rawOutput
180186
181- The CoScale api configuration (authentication) by default will be taken from api.conf file,
182- placed in the same folder with the cli-cmd. api.conf file it is the same configuration file
183- used by the CoScale agent. If the api.conf file doesn't exists, the informations also can be
184- provided on the command line using:
187+ By default the CoScale api credentials (authentication) will be taken from api.conf
188+ located in the same directory as the coscale-cli binary. If the file does not exist,
189+ the credentials can also be provided on the command line using:
185190 --api-url
186191 Base url for the api (optional, default = "https://api.coscale.com/").
187192 --app-id
188193 The application id.
189194 --access-token
190195 A valid access token for the given application.
191196
192- Use "cli-cmd [object] <help>" for more information about a command.
197+ Use "coscale-cli [object] <help>" for more information about a command.
193198`
199+
200+ // GetConfigPath is used to return the absolut path of the api configuration file
201+ func GetConfigPath () (string , error ) {
202+ configFile := "/api.conf"
203+ dir , err := filepath .Abs (filepath .Dir (os .Args [0 ]))
204+ if err != nil {
205+ os .Exit (EXIT_FLAG_ERROR )
206+ }
207+ configPath := dir + configFile
208+ if _ , err := os .Stat (configPath ); err == nil {
209+ return configPath , nil
210+ }
211+ var cmdName string
212+ if runtime .GOOS == "windows" {
213+ cmdName = "where"
214+ } else {
215+ cmdName = "which"
216+ }
217+ response , err := GetCommandOutput (cmdName , 2 * time .Second , os .Args [0 ])
218+ path := bytes .Split (response , []byte ("\n " ))[0 ]
219+ if err != nil {
220+ return "" , err
221+ }
222+ return filepath .Dir (string (path )) + configFile , nil
223+ }
224+
225+ // GetCommandOutput returns stdout of command as a string
226+ func GetCommandOutput (command string , timeout time.Duration , arg ... string ) ([]byte , error ) {
227+ var err error
228+ var stdOut bytes.Buffer
229+ var stdErr bytes.Buffer
230+ var c = make (chan []byte )
231+ cmd := exec .Command (command , arg ... )
232+ cmd .Stdout = & stdOut
233+ cmd .Stderr = & stdErr
234+ if err = cmd .Start (); err != nil {
235+ return nil , fmt .Errorf ("%s %s" , err .Error (), stdErr .String ())
236+ }
237+ go func () {
238+ err = cmd .Wait ()
239+ c <- stdOut .Bytes ()
240+ }()
241+ time .AfterFunc (timeout , func () {
242+ cmd .Process .Kill ()
243+ err = errors .New ("Maxruntime exceeded" )
244+ c <- nil
245+ })
246+ response := <- c
247+ if err != nil {
248+ fmt .Errorf ("%s %s" , err .Error (), stdErr .String ())
249+ }
250+ return response , nil
251+ }
0 commit comments