Skip to content

Commit fe0cced

Browse files
committed
handle ct state in helpers
1 parent 906154a commit fe0cced

File tree

2 files changed

+36
-15
lines changed

2 files changed

+36
-15
lines changed

internal/orchestrator/helpers.go

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import (
2020
"errors"
2121
"fmt"
2222
"log/slog"
23+
"regexp"
2324
"slices"
25+
"strconv"
2426
"strings"
2527

2628
"github.com/arduino/go-paths-helper"
@@ -50,12 +52,11 @@ type containerState struct {
5052
// For app that have at least 1 dependency, we calculate the overall state
5153
// as follow:
5254
//
53-
// running: all running
54-
// stopped: all stopped
55-
// failed: at least one failed
56-
// stopping: at least one stopping
57-
// stopped: at least one stopped
58-
// starting: at least one starting
55+
// running: all running
56+
// stopped: all stopped
57+
// failed: at least one failed
58+
// stopping: at least one stopping
59+
// starting: at least one starting
5960
func parseAppStatus(containers []container.Summary) []AppStatusInfo {
6061
apps := make([]AppStatusInfo, 0, len(containers))
6162
appsStatusMap := make(map[string][]containerState)
@@ -68,12 +69,6 @@ func parseAppStatus(containers []container.Summary) []AppStatusInfo {
6869
Status: StatusFromDockerState(c.State),
6970
StatusMessage: c.Status,
7071
})
71-
slog.Debug("Container status",
72-
slog.String("appPath", appPath),
73-
slog.String("containerID", c.ID),
74-
slog.String("state", string(c.State)),
75-
slog.String("statusMessage", c.Status),
76-
)
7772
}
7873

7974
appendResult := func(appPath *paths.Path, status Status) {
@@ -105,9 +100,7 @@ func parseAppStatus(containers []container.Summary) []AppStatusInfo {
105100
appendResult(appPath, StatusFailed)
106101
continue
107102
}
108-
if slices.ContainsFunc(s, func(v containerState) bool {
109-
return v.Status == StatusStopped && strings.Contains(v.StatusMessage, "Exited (0)")
110-
}) {
103+
if slices.ContainsFunc(s, func(v containerState) bool { return v.Status == StatusStopped && checkExitCode(v) }) {
111104
appendResult(appPath, StatusFailed)
112105
continue
113106
}
@@ -272,3 +265,20 @@ func setStatusLeds(trigger LedTrigger) error {
272265
}
273266
return nil
274267
}
268+
269+
func checkExitCode(state containerState) bool {
270+
var exitCodeRegex = regexp.MustCompile(`Exited \((\d+)\)`)
271+
result := false
272+
matches := exitCodeRegex.FindStringSubmatch(state.StatusMessage)
273+
274+
exitCode, err := strconv.Atoi(matches[1])
275+
if err != nil {
276+
slog.Error("Failed to parse exit code from status message", slog.String("statusMessage", state.StatusMessage), slog.String("error", err.Error()))
277+
return false
278+
}
279+
if exitCode >= 0 && exitCode < 128 {
280+
result = true
281+
}
282+
283+
return result
284+
}

internal/orchestrator/helpers_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,46 +27,55 @@ func TestParseAppStatus(t *testing.T) {
2727
tests := []struct {
2828
name string
2929
containerState []container.ContainerState
30+
statusMessage []string
3031
want Status
3132
}{
3233
{
3334
name: "everything running",
3435
containerState: []container.ContainerState{container.StateRunning, container.StateRunning},
36+
statusMessage: []string{"Up 5 minutes", "Up 10 minutes"},
3537
want: StatusRunning,
3638
},
3739
{
3840
name: "everything stopped",
3941
containerState: []container.ContainerState{container.StateCreated, container.StatePaused, container.StateExited},
42+
statusMessage: []string{"Created", "Paused", "Exited (137)"},
4043
want: StatusStopped,
4144
},
4245
{
4346
name: "failed container",
4447
containerState: []container.ContainerState{container.StateRunning, container.StateDead},
48+
statusMessage: []string{"Up 5 minutes", "Dead"},
4549
want: StatusFailed,
4650
},
4751
{
4852
name: "failed container takes precedence over stopping and starting",
4953
containerState: []container.ContainerState{container.StateRunning, container.StateDead, container.StateRemoving, container.StateRestarting},
54+
statusMessage: []string{"Up 5 minutes", "Dead", "Removing", "Restarting"},
5055
want: StatusFailed,
5156
},
5257
{
5358
name: "stopping",
5459
containerState: []container.ContainerState{container.StateRunning, container.StateRemoving},
60+
statusMessage: []string{"Up 5 minutes", "Removing"},
5561
want: StatusStopping,
5662
},
5763
{
5864
name: "stopping takes precedence over starting",
5965
containerState: []container.ContainerState{container.StateRunning, container.StateRestarting, container.StateRemoving},
66+
statusMessage: []string{"Up 5 minutes", "Restarting", "Removing"},
6067
want: StatusStopping,
6168
},
6269
{
6370
name: "starting",
6471
containerState: []container.ContainerState{container.StateRestarting, container.StateExited},
72+
statusMessage: []string{"Restarting", "Exited (129)"},
6573
want: StatusStarting,
6674
},
6775
{
6876
name: "failed",
6977
containerState: []container.ContainerState{container.StateRestarting, container.StateExited},
78+
statusMessage: []string{"Restarting", "Exited (0)"},
7079
want: StatusFailed,
7180
},
7281
}
@@ -77,8 +86,10 @@ func TestParseAppStatus(t *testing.T) {
7786
return container.Summary{
7887
Labels: map[string]string{DockerAppPathLabel: "path1"},
7988
State: c,
89+
Status: "Exited (129)",
8090
}
8191
})
92+
8293
res := parseAppStatus(input)
8394
require.Len(t, res, 1)
8495
require.Equal(t, tc.want, res[0].Status)

0 commit comments

Comments
 (0)