Skip to content

Commit 91cd5a6

Browse files
giulio93lucarin91
andauthored
fix: make app failed if a container is stopped (#116)
* add status stopped * Apply suggestion from @lucarin91 Co-authored-by: Luca Rinaldi <l.rinaldi@arduino.cc> * Add state failed * States * revert * containerState struct with Status and StatusMessage * handle ct state in helpers * add status message to * check function in status * Update internal/orchestrator/status.go Co-authored-by: Luca Rinaldi <l.rinaldi@arduino.cc> * Update internal/orchestrator/status.go Co-authored-by: Luca Rinaldi <l.rinaldi@arduino.cc> --------- Co-authored-by: Luca Rinaldi <l.rinaldi@arduino.cc>
1 parent 1933e51 commit 91cd5a6

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

internal/orchestrator/helpers.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ func parseAppStatus(containers []container.Summary) []AppStatusInfo {
5757
if !ok {
5858
continue
5959
}
60-
appsStatusMap[appPath] = append(appsStatusMap[appPath], StatusFromDockerState(c.State))
60+
appsStatusMap[appPath] = append(appsStatusMap[appPath], StatusFromDockerState(c.State, c.Status))
61+
6162
}
6263

6364
appendResult := func(appPath *paths.Path, status Status) {

internal/orchestrator/helpers_test.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,60 +20,75 @@ import (
2020

2121
"github.com/docker/docker/api/types/container"
2222
"github.com/stretchr/testify/require"
23-
"go.bug.st/f"
2423
)
2524

2625
func TestParseAppStatus(t *testing.T) {
2726
tests := []struct {
2827
name string
2928
containerState []container.ContainerState
29+
statusMessage []string
3030
want Status
3131
}{
3232
{
3333
name: "everything running",
3434
containerState: []container.ContainerState{container.StateRunning, container.StateRunning},
35+
statusMessage: []string{"Up 5 minutes", "Up 10 minutes"},
3536
want: StatusRunning,
3637
},
3738
{
3839
name: "everything stopped",
3940
containerState: []container.ContainerState{container.StateCreated, container.StatePaused, container.StateExited},
41+
statusMessage: []string{"Created", "Paused", "Exited (137)"},
4042
want: StatusStopped,
4143
},
4244
{
4345
name: "failed container",
4446
containerState: []container.ContainerState{container.StateRunning, container.StateDead},
47+
statusMessage: []string{"Up 5 minutes", "Dead"},
4548
want: StatusFailed,
4649
},
4750
{
4851
name: "failed container takes precedence over stopping and starting",
4952
containerState: []container.ContainerState{container.StateRunning, container.StateDead, container.StateRemoving, container.StateRestarting},
53+
statusMessage: []string{"Up 5 minutes", "Dead", "Removing", "Restarting"},
5054
want: StatusFailed,
5155
},
5256
{
5357
name: "stopping",
5458
containerState: []container.ContainerState{container.StateRunning, container.StateRemoving},
59+
statusMessage: []string{"Up 5 minutes", "Removing"},
5560
want: StatusStopping,
5661
},
5762
{
5863
name: "stopping takes precedence over starting",
5964
containerState: []container.ContainerState{container.StateRunning, container.StateRestarting, container.StateRemoving},
65+
statusMessage: []string{"Up 5 minutes", "Restarting", "Removing"},
6066
want: StatusStopping,
6167
},
6268
{
6369
name: "starting",
6470
containerState: []container.ContainerState{container.StateRestarting, container.StateExited},
71+
statusMessage: []string{"Restarting", "Exited (129)"},
6572
want: StatusStarting,
6673
},
74+
{
75+
name: "failed",
76+
containerState: []container.ContainerState{container.StateRestarting, container.StateExited},
77+
statusMessage: []string{"Restarting", "Exited (1)"},
78+
want: StatusFailed,
79+
},
6780
}
6881

6982
for _, tc := range tests {
7083
t.Run(tc.name, func(t *testing.T) {
71-
input := f.Map(tc.containerState, func(c container.ContainerState) container.Summary {
72-
return container.Summary{
84+
var input []container.Summary
85+
for i, c := range tc.containerState {
86+
input = append(input, container.Summary{
7387
Labels: map[string]string{DockerAppPathLabel: "path1"},
7488
State: c,
75-
}
76-
})
89+
Status: tc.statusMessage[i],
90+
})
91+
}
7792
res := parseAppStatus(input)
7893
require.Len(t, res, 1)
7994
require.Equal(t, tc.want, res[0].Status)

internal/orchestrator/status.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ package orchestrator
1717

1818
import (
1919
"fmt"
20+
"regexp"
21+
"strconv"
2022

2123
"github.com/docker/docker/api/types/container"
24+
"go.bug.st/f"
2225
)
2326

2427
type Status string
@@ -31,15 +34,21 @@ const (
3134
StatusFailed Status = "failed"
3235
)
3336

34-
func StatusFromDockerState(s container.ContainerState) Status {
37+
func StatusFromDockerState(s container.ContainerState, statusMessage string) Status {
3538
switch s {
3639
case container.StateRunning:
3740
return StatusRunning
3841
case container.StateRestarting:
3942
return StatusStarting
4043
case container.StateRemoving:
4144
return StatusStopping
42-
case container.StateCreated, container.StateExited, container.StatePaused:
45+
case container.StateCreated, container.StatePaused:
46+
return StatusStopped
47+
case container.StateExited:
48+
if !isExitBySignal(statusMessage) {
49+
// The app exited on its own, which we consider a failure.
50+
return StatusFailed
51+
}
4352
return StatusStopped
4453
case container.StateDead:
4554
return StatusFailed
@@ -65,3 +74,17 @@ func (s Status) Validate() error {
6574
func (s Status) AllowedStatuses() []Status {
6675
return []Status{StatusStarting, StatusRunning, StatusStopping, StatusStopped, StatusFailed}
6776
}
77+
78+
func isExitBySignal(statusMessage string) bool {
79+
var exitCodeRegex = regexp.MustCompile(`Exited \((\d+)\)`)
80+
matches := exitCodeRegex.FindStringSubmatch(statusMessage)
81+
if len(matches) < 2 {
82+
// not matching an exit code
83+
return false
84+
}
85+
exitCode := f.Must(strconv.Atoi(matches[1]))
86+
87+
// posix exit code greater than 128+n means terminated by signal https://tldp.org/LDP/abs/html/exitcodes.html
88+
return exitCode > 128
89+
90+
}

0 commit comments

Comments
 (0)