Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a58a518

Browse files
[CLI] Add a "restart" app command (#37)
The CLI provides a command to start and stop an app/example. Often it's useful to have a restart command, that will stop and start again the same app. This is needed only for the CLI interface. The command already exists. But error management should be improved: restarting an app X when app Y is running does not show a clear error if the app running is not the one being restarted: error if no app is running: just start the app
1 parent 7508a4b commit a58a518

File tree

2 files changed

+106
-6
lines changed

2 files changed

+106
-6
lines changed

‎cmd/arduino-app-cli/app/restart.go‎

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,18 @@
1616
package app
1717

1818
import (
19+
"context"
20+
"fmt"
21+
1922
"github.com/spf13/cobra"
23+
"golang.org/x/text/cases"
24+
"golang.org/x/text/language"
2025

2126
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/completion"
27+
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/internal/servicelocator"
2228
"github.com/arduino/arduino-app-cli/cmd/feedback"
29+
"github.com/arduino/arduino-app-cli/internal/orchestrator"
30+
"github.com/arduino/arduino-app-cli/internal/orchestrator/app"
2331
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2432
)
2533

@@ -32,17 +40,63 @@ func newRestartCmd(cfg config.Configuration) *cobra.Command {
3240
if len(args) == 0 {
3341
return cmd.Help()
3442
}
35-
app, err := Load(args[0])
43+
appToStart, err := Load(args[0])
3644
if err != nil {
3745
feedback.Fatal(err.Error(), feedback.ErrBadArgument)
38-
return nil
39-
}
40-
if err := stopHandler(cmd.Context(), app); err != nil {
41-
feedback.Warnf("failed to stop app: %s", err.Error())
4246
}
43-
return startHandler(cmd.Context(), cfg, app)
47+
return restartHandler(cmd.Context(), cfg, appToStart)
4448
},
4549
ValidArgsFunction: completion.ApplicationNames(cfg),
4650
}
4751
return cmd
4852
}
53+
54+
func restartHandler(ctx context.Context, cfg config.Configuration, app app.ArduinoApp) error {
55+
out, _, getResult := feedback.OutputStreams()
56+
57+
stream := orchestrator.RestartApp(
58+
ctx,
59+
servicelocator.GetDockerClient(),
60+
servicelocator.GetProvisioner(),
61+
servicelocator.GetModelsIndex(),
62+
servicelocator.GetBricksIndex(),
63+
app,
64+
cfg,
65+
servicelocator.GetStaticStore(),
66+
)
67+
for message := range stream {
68+
switch message.GetType() {
69+
case orchestrator.ProgressType:
70+
fmt.Fprintf(out, "Progress[%s]: %.0f%%\n", message.GetProgress().Name, message.GetProgress().Progress)
71+
case orchestrator.InfoType:
72+
fmt.Fprintln(out, "[INFO]", message.GetData())
73+
case orchestrator.ErrorType:
74+
errMesg := cases.Title(language.AmericanEnglish).String(message.GetError().Error())
75+
feedback.Fatal(fmt.Sprintf("[ERROR] %s", errMesg), feedback.ErrGeneric)
76+
return nil
77+
}
78+
}
79+
80+
outputResult := getResult()
81+
feedback.PrintResult(restartAppResult{
82+
AppName: app.Name,
83+
Status: "restarted",
84+
Output: outputResult,
85+
})
86+
87+
return nil
88+
}
89+
90+
type restartAppResult struct {
91+
AppName string `json:"app_name"`
92+
Status string `json:"status"`
93+
Output *feedback.OutputStreamsResult `json:"output,omitempty"`
94+
}
95+
96+
func (r restartAppResult) String() string {
97+
return fmt.Sprintf("✓ App %q restarted successfully", r.AppName)
98+
}
99+
100+
func (r restartAppResult) Data() interface{} {
101+
return r
102+
}

‎internal/orchestrator/orchestrator.go‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ func StartApp(
131131
yield(StreamMessage{error: fmt.Errorf("app %q is running", running.Name)})
132132
return
133133
}
134+
if !yield(StreamMessage{data: fmt.Sprintf("Starting app %q", app.Name)}) {
135+
return
136+
}
134137

135138
if err := setStatusLeds(LedTriggerNone); err != nil {
136139
slog.Debug("unable to set status leds", slog.String("error", err.Error()))
@@ -379,6 +382,9 @@ func stopAppWithCmd(ctx context.Context, app app.ArduinoApp, cmd string) iter.Se
379382
ctx, cancel := context.WithCancel(ctx)
380383
defer cancel()
381384

385+
if !yield(StreamMessage{data: fmt.Sprintf("Stopping app %q", app.Name)}) {
386+
return
387+
}
382388
if err := setStatusLeds(LedTriggerDefault); err != nil {
383389
slog.Debug("unable to set status leds", slog.String("error", err.Error()))
384390
}
@@ -427,6 +433,46 @@ func StopAndDestroyApp(ctx context.Context, app app.ArduinoApp) iter.Seq[StreamM
427433
return stopAppWithCmd(ctx, app, "down")
428434
}
429435

436+
func RestartApp(
437+
ctx context.Context,
438+
docker command.Cli,
439+
provisioner *Provision,
440+
modelsIndex *modelsindex.ModelsIndex,
441+
bricksIndex *bricksindex.BricksIndex,
442+
appToStart app.ArduinoApp,
443+
cfg config.Configuration,
444+
staticStore *store.StaticStore,
445+
) iter.Seq[StreamMessage] {
446+
return func(yield func(StreamMessage) bool) {
447+
ctx, cancel := context.WithCancel(ctx)
448+
defer cancel()
449+
runningApp, err := getRunningApp(ctx, docker.Client())
450+
if err != nil {
451+
yield(StreamMessage{error: err})
452+
return
453+
}
454+
455+
if runningApp != nil {
456+
if runningApp.FullPath.String() != appToStart.FullPath.String() {
457+
yield(StreamMessage{error: fmt.Errorf("another app %q is running", runningApp.Name)})
458+
return
459+
}
460+
461+
stopStream := StopApp(ctx, *runningApp)
462+
for msg := range stopStream {
463+
if !yield(msg) {
464+
return
465+
}
466+
if msg.error != nil {
467+
return
468+
}
469+
}
470+
}
471+
startStream := StartApp(ctx, docker, provisioner, modelsIndex, bricksIndex, appToStart, cfg, staticStore)
472+
startStream(yield)
473+
}
474+
}
475+
430476
func StartDefaultApp(
431477
ctx context.Context,
432478
docker command.Cli,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /