Skip to content
Open
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
46 changes: 34 additions & 12 deletions internal/orchestrator/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"context"
"errors"
"fmt"
"log/slog"
"slices"
"strings"

Expand All @@ -39,25 +40,40 @@ type AppStatusInfo struct {
Status Status
}

type containerState struct {
Status Status
StatusMessage string
}

// parseAppStatus takes all the containers that matches the DockerAppLabel,
// and construct a map of the state of an app and all its dependencies state.
// For app that have at least 1 dependency, we calculate the overall state
// as follow:
//
// running: all running
// stopped: all stopped
// failed: at least one failed
// stopping: at least one stopping
// starting: at least one starting
// running: all running
// stopped: all stopped
// failed: at least one failed
// stopping: at least one stopping
// stopped: at least one stopped
// starting: at least one starting
func parseAppStatus(containers []container.Summary) []AppStatusInfo {
apps := make([]AppStatusInfo, 0, len(containers))
appsStatusMap := make(map[string][]Status)
appsStatusMap := make(map[string][]containerState)
for _, c := range containers {
appPath, ok := c.Labels[DockerAppPathLabel]
if !ok {
continue
}
appsStatusMap[appPath] = append(appsStatusMap[appPath], StatusFromDockerState(c.State))
appsStatusMap[appPath] = append(appsStatusMap[appPath], containerState{
Status: StatusFromDockerState(c.State),
StatusMessage: c.Status,
})
slog.Debug("Container status",
slog.String("appPath", appPath),
slog.String("containerID", c.ID),
slog.String("state", string(c.State)),
slog.String("statusMessage", c.Status),
)
}

appendResult := func(appPath *paths.Path, status Status) {
Expand All @@ -73,27 +89,33 @@ func parseAppStatus(containers []container.Summary) []AppStatusInfo {
appPath := paths.New(appPath)

// running: all running
if !slices.ContainsFunc(s, func(v Status) bool { return v != StatusRunning }) {
if !slices.ContainsFunc(s, func(v containerState) bool { return v.Status != StatusRunning }) {
appendResult(appPath, StatusRunning)
continue
}
// stopped: all stopped
if !slices.ContainsFunc(s, func(v Status) bool { return v != StatusStopped }) {
if !slices.ContainsFunc(s, func(v containerState) bool { return v.Status != StatusStopped }) {
appendResult(appPath, StatusStopped)
continue
}

// ...else we have multiple different status we calculate the status
// among the possible left: {failed, stopping, starting}
if slices.ContainsFunc(s, func(v Status) bool { return v == StatusFailed }) {
if slices.ContainsFunc(s, func(v containerState) bool { return v.Status == StatusFailed }) {
appendResult(appPath, StatusFailed)
continue
}
if slices.ContainsFunc(s, func(v containerState) bool {
return v.Status == StatusStopped && strings.Contains(v.StatusMessage, "Exited (0)")
}) {
appendResult(appPath, StatusFailed)
continue
}
if slices.ContainsFunc(s, func(v Status) bool { return v == StatusStopping }) {
if slices.ContainsFunc(s, func(v containerState) bool { return v.Status == StatusStopping }) {
appendResult(appPath, StatusStopping)
continue
}
if slices.ContainsFunc(s, func(v Status) bool { return v == StatusStarting }) {
if slices.ContainsFunc(s, func(v containerState) bool { return v.Status == StatusStarting }) {
appendResult(appPath, StatusStarting)
continue
}
Expand Down
Loading