Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/arduino-app-cli/app/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/spf13/cobra"

"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/completion"
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/internal/servicelocator"
"github.com/arduino/arduino-app-cli/cmd/feedback"
"github.com/arduino/arduino-app-cli/internal/orchestrator"
"github.com/arduino/arduino-app-cli/internal/orchestrator/app"
Expand Down Expand Up @@ -53,7 +54,7 @@ func newStopCmd(cfg config.Configuration) *cobra.Command {
func stopHandler(ctx context.Context, app app.ArduinoApp) error {
out, _, getResult := feedback.OutputStreams()

for message := range orchestrator.StopApp(ctx, app) {
for message := range orchestrator.StopApp(ctx, servicelocator.GetDockerClient(), app) {
switch message.GetType() {
case orchestrator.ProgressType:
fmt.Fprintf(out, "Progress[%s]: %.0f%%\n", message.GetProgress().Name, message.GetProgress().Progress)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func NewHTTPRouter(
mux.Handle("POST /v1/apps/{appID}/start", handlers.HandleAppStart(dockerClient, provisioner, modelsIndex, bricksIndex, idProvider, cfg, staticStore))
mux.Handle("POST /v1/apps/{appID}/stop", handlers.HandleAppStop(dockerClient, idProvider))
mux.Handle("POST /v1/apps/{appID}/clone", handlers.HandleAppClone(dockerClient, idProvider, cfg))
mux.Handle("DELETE /v1/apps/{appID}", handlers.HandleAppDelete(idProvider))
mux.Handle("DELETE /v1/apps/{appID}", handlers.HandleAppDelete(dockerClient, idProvider))
mux.Handle("GET /v1/apps/{appID}/exposed-ports", handlers.HandleAppPorts(bricksIndex, idProvider))
mux.Handle("PUT /v1/apps/{appID}/sketch/libraries/{libRef}", handlers.HandleSketchAddLibrary(idProvider))
mux.Handle("DELETE /v1/apps/{appID}/sketch/libraries/{libRef}", handlers.HandleSketchRemoveLibrary(idProvider))
Expand Down
9 changes: 7 additions & 2 deletions internal/api/handlers/app_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@ import (
"log/slog"
"net/http"

"github.com/docker/cli/cli/command"

"github.com/arduino/arduino-app-cli/internal/api/models"
"github.com/arduino/arduino-app-cli/internal/orchestrator"
"github.com/arduino/arduino-app-cli/internal/orchestrator/app"
"github.com/arduino/arduino-app-cli/internal/render"
)

func HandleAppDelete(idProvider *app.IDProvider) http.HandlerFunc {
func HandleAppDelete(
dockerClient command.Cli,
idProvider *app.IDProvider,
) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, err := idProvider.IDFromBase64(r.PathValue("appID"))
if err != nil {
Expand All @@ -44,7 +49,7 @@ func HandleAppDelete(idProvider *app.IDProvider) http.HandlerFunc {
return
}

err = orchestrator.DeleteApp(r.Context(), app)
err = orchestrator.DeleteApp(r.Context(), dockerClient, app)
if err != nil {
slog.Error("Unable to delete the app", slog.String("error", err.Error()))
render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to delete the app"})
Expand Down
2 changes: 1 addition & 1 deletion internal/api/handlers/app_stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func HandleAppStop(
type log struct {
Message string `json:"message"`
}
for item := range orchestrator.StopApp(r.Context(), app) {
for item := range orchestrator.StopApp(r.Context(), dockerClient, app) {
switch item.GetType() {
case orchestrator.ProgressType:
sseStream.Send(render.SSEEvent{Type: "progress", Data: progress(*item.GetProgress())})
Expand Down
2 changes: 1 addition & 1 deletion internal/orchestrator/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func CleanAppCache(
return ErrCleanCacheRunningApp
}
// We try to remove docker related resources at best effort
for range StopAndDestroyApp(ctx, app) {
for range StopAndDestroyApp(ctx, docker, app) {
// just consume the iterator
}
}
Expand Down
38 changes: 28 additions & 10 deletions internal/orchestrator/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,21 @@ func getVideoDevices() map[int]string {
return deviceMap
}

func stopAppWithCmd(ctx context.Context, app app.ArduinoApp, cmd string) iter.Seq[StreamMessage] {
func stopAppWithCmd(ctx context.Context, docker command.Cli, app app.ArduinoApp, cmd string) iter.Seq[StreamMessage] {
return func(yield func(StreamMessage) bool) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()

appStatus, err := getAppStatus(ctx, docker, app)
if err != nil {
yield(StreamMessage{error: err})
return
}
if appStatus.Status != StatusStarting && appStatus.Status != StatusRunning {
yield(StreamMessage{data: fmt.Sprintf("app %q is not running", app.Name)})
return
}

if !yield(StreamMessage{data: fmt.Sprintf("Stopping app %q", app.Name)}) {
return
}
Expand All @@ -395,6 +405,7 @@ func stopAppWithCmd(ctx context.Context, app app.ArduinoApp, cmd string) iter.Se
return
}
})

if app.MainSketchPath != nil {
// TODO: check that the app sketch is running before attempting to stop it.

Expand Down Expand Up @@ -425,12 +436,12 @@ func stopAppWithCmd(ctx context.Context, app app.ArduinoApp, cmd string) iter.Se
}
}

func StopApp(ctx context.Context, app app.ArduinoApp) iter.Seq[StreamMessage] {
return stopAppWithCmd(ctx, app, "stop")
func StopApp(ctx context.Context, dockerClient command.Cli, app app.ArduinoApp) iter.Seq[StreamMessage] {
return stopAppWithCmd(ctx, dockerClient, app, "stop")
}

func StopAndDestroyApp(ctx context.Context, app app.ArduinoApp) iter.Seq[StreamMessage] {
return stopAppWithCmd(ctx, app, "down")
func StopAndDestroyApp(ctx context.Context, dockerClient command.Cli, app app.ArduinoApp) iter.Seq[StreamMessage] {
return stopAppWithCmd(ctx, dockerClient, app, "down")
}

func RestartApp(
Expand Down Expand Up @@ -458,7 +469,7 @@ func RestartApp(
return
}

stopStream := StopApp(ctx, *runningApp)
stopStream := StopApp(ctx, docker, *runningApp)
for msg := range stopStream {
if !yield(msg) {
return
Expand Down Expand Up @@ -888,12 +899,19 @@ func CloneApp(
return CloneAppResponse{ID: id}, nil
}

func DeleteApp(ctx context.Context, app app.ArduinoApp) error {
for msg := range StopApp(ctx, app) {
if msg.error != nil {
return fmt.Errorf("failed to stop app: %w", msg.error)
func DeleteApp(ctx context.Context, dockerClient command.Cli, app app.ArduinoApp) error {

runningApp, err := getRunningApp(ctx, dockerClient.Client())
if err != nil {
return err
}
if runningApp != nil && runningApp.FullPath.EqualsTo(app.FullPath) {
// We try to remove docker related resources at best effort
for range StopAndDestroyApp(ctx, dockerClient, app) {
// just consume the iterator
}
}

return app.FullPath.RemoveAll()
}

Expand Down
2 changes: 1 addition & 1 deletion internal/orchestrator/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func SystemCleanup(ctx context.Context, cfg config.Configuration, staticStore *s
feedback.Warnf("failed to get running app - %v", err)
}
if runningApp != nil {
for item := range StopAndDestroyApp(ctx, *runningApp) {
for item := range StopAndDestroyApp(ctx, docker, *runningApp) {
if item.GetType() == ErrorType {
feedback.Warnf("failed to stop and destroy running app - %v", item.GetError())
break
Expand Down