@@ -2,19 +2,15 @@ package main
22
33import (
44 "context"
5- "encoding/base64"
6- "encoding/json"
75 "errors"
86 "fmt"
9- "log/slog"
10- "os"
11- "strings"
127
138 "github.com/arduino/go-paths-helper"
149 "github.com/spf13/cobra"
15- "mkuznets.com/go/tabwriter"
1610
1711 "github.com/bcmi-labs/orchestrator/cmd/arduino-app-cli/internal/servicelocator"
12+ "github.com/bcmi-labs/orchestrator/cmd/feedback"
13+ "github.com/bcmi-labs/orchestrator/cmd/results"
1814 "github.com/bcmi-labs/orchestrator/internal/orchestrator"
1915 "github.com/bcmi-labs/orchestrator/internal/orchestrator/app"
2016)
@@ -115,10 +111,11 @@ func newRestartCmd() *cobra.Command {
115111 }
116112 app , err := loadApp (args [0 ])
117113 if err != nil {
118- return err
114+ feedback .Fatal (err .Error (), feedback .ErrBadArgument )
115+ return nil
119116 }
120117 if err := stopHandler (cmd .Context (), app ); err != nil {
121- slog . Warn ( "failed to stop app" , "error" , err )
118+ feedback . Warning ( fmt . Sprintf ( "failed to stop app: %s" , err . Error ()) )
122119 }
123120 return startHandler (cmd .Context (), app )
124121 },
@@ -165,7 +162,7 @@ func newListCmd() *cobra.Command {
165162 Use : "list" ,
166163 Short : "List all running Python apps" ,
167164 RunE : func (cmd * cobra.Command , args []string ) error {
168- return listHandler (cmd .Context (), jsonFormat )
165+ return listHandler (cmd .Context ())
169166 },
170167 }
171168
@@ -183,14 +180,6 @@ func newPsCmd() *cobra.Command {
183180 }
184181}
185182
186- func renderDefaultApp (app * app.ArduinoApp ) {
187- if app == nil {
188- fmt .Println ("No default app set" )
189- } else {
190- fmt .Printf ("Default app: %s (%s)\n " , app .Name , app .FullPath )
191- }
192- }
193-
194183func newPropertiesCmd () * cobra.Command {
195184 cmd := & cobra.Command {
196185 Use : "properties" ,
@@ -209,9 +198,11 @@ func newPropertiesCmd() *cobra.Command {
209198 }
210199 def , err := orchestrator .GetDefaultApp ()
211200 if err != nil {
212- return err
201+ feedback . Fatal ( err . Error (), feedback . ErrGeneric )
213202 }
214- renderDefaultApp (def )
203+ feedback .PrintResult (results.DefaultAppResult {
204+ App : def ,
205+ })
215206 return nil
216207 },
217208 })
@@ -228,17 +219,24 @@ func newPropertiesCmd() *cobra.Command {
228219 }
229220 // Remove default app.
230221 if len (args ) == 1 || args [1 ] == "none" {
231- return orchestrator .SetDefaultApp (nil )
222+ if err := orchestrator .SetDefaultApp (nil ); err != nil {
223+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
224+ return nil
225+ }
226+ feedback .PrintResult (results.DefaultAppResult {App : nil })
227+ return nil
232228 }
233229
234230 app , err := loadApp (args [1 ])
235231 if err != nil {
236- return err
232+ feedback .Fatal (err .Error (), feedback .ErrBadArgument )
233+ return nil
237234 }
238235 if err := orchestrator .SetDefaultApp (& app ); err != nil {
239- return err
236+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
237+ return nil
240238 }
241- renderDefaultApp ( & app )
239+ feedback . PrintResult (results. DefaultAppResult { App : & app } )
242240 return nil
243241 },
244242 })
@@ -247,6 +245,8 @@ func newPropertiesCmd() *cobra.Command {
247245}
248246
249247func startHandler (ctx context.Context , app app.ArduinoApp ) error {
248+ out , _ , getResult := feedback .OutputStreams ()
249+
250250 stream := orchestrator .StartApp (
251251 ctx ,
252252 servicelocator .GetDockerClient (),
@@ -258,31 +258,57 @@ func startHandler(ctx context.Context, app app.ArduinoApp) error {
258258 for message := range stream {
259259 switch message .GetType () {
260260 case orchestrator .ProgressType :
261- slog . Info ( "progress" , slog . Float64 ( "progress" , float64 (message .GetProgress ().Progress )) )
261+ fmt . Fprintf ( out , "Progress: %.0f%% \n " , float64 (message .GetProgress ().Progress )* 100 )
262262 case orchestrator .InfoType :
263- slog . Info ( "log" , slog . String ( "message " , message .GetData () ))
263+ fmt . Fprintln ( out , "[INFO] " , message .GetData ())
264264 case orchestrator .ErrorType :
265- return errors .New (message .GetError ().Error ())
265+ err := errors .New (message .GetError ().Error ())
266+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
267+ return nil
266268 }
267269 }
270+ outputResult := getResult ()
271+ feedback .PrintResult (results.StartAppResult {
272+ AppName : app .Name ,
273+ Status : "started" ,
274+ Output : outputResult ,
275+ })
276+
268277 return nil
269278}
270279
271280func stopHandler (ctx context.Context , app app.ArduinoApp ) error {
281+ out , _ , getResult := feedback .OutputStreams ()
282+
272283 for message := range orchestrator .StopApp (ctx , app ) {
273284 switch message .GetType () {
274285 case orchestrator .ProgressType :
275- slog . Info ( "progress" , slog . Float64 ( "progress" , float64 (message .GetProgress ().Progress )) )
286+ fmt . Fprintf ( out , "Progress: %.0f%% \n " , float64 (message .GetProgress ().Progress )* 100 )
276287 case orchestrator .InfoType :
277- slog . Info ( "log" , slog . String ( "message " , message .GetData () ))
288+ fmt . Fprintln ( out , "[INFO] " , message .GetData ())
278289 case orchestrator .ErrorType :
279- return errors .New (message .GetError ().Error ())
290+ err := errors .New (message .GetError ().Error ())
291+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
292+ return nil
280293 }
281294 }
295+ outputResult := getResult ()
296+
297+ feedback .PrintResult (results.StopAppResult {
298+ AppName : app .Name ,
299+ Status : "stopped" ,
300+ Output : outputResult ,
301+ })
282302 return nil
283303}
284304
285305func logsHandler (ctx context.Context , app app.ArduinoApp , tail * uint64 ) error {
306+ stdout , _ , err := feedback .DirectStreams ()
307+ if err != nil {
308+ feedback .Fatal (err .Error (), feedback .ErrBadArgument )
309+ return nil
310+ }
311+
286312 logsIter , err := orchestrator .AppLogs (
287313 ctx ,
288314 app ,
@@ -293,15 +319,16 @@ func logsHandler(ctx context.Context, app app.ArduinoApp, tail *uint64) error {
293319 },
294320 )
295321 if err != nil {
296- return err
322+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
323+ return nil
297324 }
298325 for msg := range logsIter {
299- fmt .Printf ( "[%s] %s\n " , msg .Name , msg .Content )
326+ fmt .Fprintf ( stdout , "[%s] %s\n " , msg .Name , msg .Content )
300327 }
301328 return nil
302329}
303330
304- func listHandler (ctx context.Context , jsonFormat bool ) error {
331+ func listHandler (ctx context.Context ) error {
305332 res , err := orchestrator .ListApps (ctx ,
306333 servicelocator .GetDockerClient (),
307334 orchestrator.ListAppRequest {
@@ -311,67 +338,14 @@ func listHandler(ctx context.Context, jsonFormat bool) error {
311338 },
312339 )
313340 if err != nil {
341+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
314342 return nil
315343 }
316344
317- idToAlias := func (id orchestrator.ID ) string {
318- v := id .String ()
319- res , err := base64 .RawURLEncoding .DecodeString (v )
320- if err != nil {
321- return v
322- }
323-
324- v = string (res )
325- if strings .Contains (v , ":" ) {
326- return v
327- }
328-
329- wd , err := paths .Getwd ()
330- if err != nil {
331- return v
332- }
333- rel , err := paths .New (v ).RelFrom (wd )
334- if err != nil {
335- return v
336- }
337- if ! strings .HasPrefix (rel .String (), "./" ) && ! strings .HasPrefix (rel .String (), "../" ) {
338- return "./" + rel .String ()
339- }
340- return rel .String ()
341- }
342-
343- if jsonFormat {
344- // Print in JSON format.
345- resJSON , err := json .Marshal (res )
346- if err != nil {
347- return nil
348- }
349- fmt .Println (string (resJSON ))
350- } else {
351- w := tabwriter .NewWriter (os .Stdout , 0 , 0 , 3 , ' ' , 0 ) // minwidth, tabwidth, padding, padchar, flags
352- fmt .Fprintln (w , "ID\t NAME\t ICON\t STATUS\t EXAMPLE" )
353-
354- for _ , app := range res .Apps {
355- fmt .Fprintf (w , "%s\t %s\t %s\t %s\t %t\n " ,
356- idToAlias (app .ID ),
357- app .Name ,
358- app .Icon ,
359- app .Status ,
360- app .Example ,
361- )
362- }
363-
364- if len (res .BrokenApps ) > 0 {
365- fmt .Fprintln (w , "\n APP\t ERROR" )
366- for _ , app := range res .BrokenApps {
367- fmt .Fprintf (w , "%s\t %s\n " ,
368- app .Name ,
369- app .Error ,
370- )
371- }
372- }
373- w .Flush ()
374- }
345+ feedback .PrintResult (results.AppListResult {
346+ Apps : res .Apps ,
347+ BrokenApps : res .BrokenApps ,
348+ })
375349
376350 return nil
377351}
@@ -380,26 +354,35 @@ func createHandler(ctx context.Context, name string, icon string, bricks []strin
380354 if fromApp != "" {
381355 wd , err := paths .Getwd ()
382356 if err != nil {
383- return err
357+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
358+ return nil
384359 }
385360 fromPath := paths .New (fromApp )
386361 if ! fromPath .IsAbs () {
387362 fromPath = wd .JoinPath (fromPath )
388363 }
389364 id , err := orchestrator .NewIDFromPath (fromPath )
390365 if err != nil {
391- return err
366+ feedback .Fatal (err .Error (), feedback .ErrBadArgument )
367+ return nil
392368 }
393369
394370 resp , err := orchestrator .CloneApp (ctx , orchestrator.CloneAppRequest {
395371 Name : & name ,
396372 FromID : id ,
397373 })
398374 if err != nil {
399- return err
375+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
376+ return nil
400377 }
401378 dst := resp .ID .ToPath ()
402- fmt .Println ("App cloned in: " , dst )
379+
380+ feedback .PrintResult (results.CreateAppResult {
381+ Result : "ok" ,
382+ Message : "App created successfully" ,
383+ Path : dst .String (),
384+ })
385+
403386 } else {
404387 resp , err := orchestrator .CreateApp (ctx , orchestrator.CreateAppRequest {
405388 Name : name ,
@@ -409,9 +392,14 @@ func createHandler(ctx context.Context, name string, icon string, bricks []strin
409392 SkipSketch : noSketch ,
410393 })
411394 if err != nil {
412- return err
395+ feedback .Fatal (err .Error (), feedback .ErrGeneric )
396+ return nil
413397 }
414- fmt .Println ("App created successfully:" , resp .ID .ToPath ().String ())
398+ feedback .PrintResult (results.CreateAppResult {
399+ Result : "ok" ,
400+ Message : "App created successfully" ,
401+ Path : resp .ID .ToPath ().String (),
402+ })
415403 }
416404 return nil
417405}
0 commit comments