Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit 2162bc9

Browse files
authored
Merge pull request #1675 from ndeloof/ps_exitcode
ps shows healthcheck only for running container
2 parents 8f2e572 + 221f420 commit 2162bc9

File tree

4 files changed

+31
-38
lines changed

4 files changed

+31
-38
lines changed

api/compose/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ type ContainerSummary struct {
284284
Service string
285285
State string
286286
Health string
287+
ExitCode int
287288
Publishers []PortPublisher
288289
}
289290

cli/cmd/compose/ps.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@ func runPs(ctx context.Context, backend compose.Service, services []string, opts
103103
}
104104
}
105105
status := container.State
106-
if container.Health != "" {
106+
if status == "running" && container.Health != "" {
107107
status = fmt.Sprintf("%s (%s)", container.State, container.Health)
108+
} else if status == "exited" || status == "dead" {
109+
status = fmt.Sprintf("%s (%d)", container.State, container.ExitCode)
108110
}
109111
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", container.Name, container.Service, status, strings.Join(ports, ", "))
110112
}

local/compose/ps.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ package compose
1919
import (
2020
"context"
2121
"fmt"
22-
23-
"golang.org/x/sync/errgroup"
22+
"sort"
2423

2524
"github.com/docker/compose-cli/api/compose"
25+
"golang.org/x/sync/errgroup"
2626
)
2727

2828
func (s *composeService) Ps(ctx context.Context, projectName string, options compose.PsOptions) ([]compose.ContainerSummary, error) {
@@ -42,6 +42,9 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options com
4242
i := i
4343
eg.Go(func() error {
4444
var publishers []compose.PortPublisher
45+
sort.Slice(container.Ports, func(i, j int) bool {
46+
return container.Ports[i].PrivatePort < container.Ports[j].PrivatePort
47+
})
4548
for _, p := range container.Ports {
4649
var url string
4750
if p.PublicPort != 0 {
@@ -60,9 +63,19 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options com
6063
return err
6164
}
6265

63-
var health string
64-
if inspect.State != nil && inspect.State.Health != nil {
65-
health = inspect.State.Health.Status
66+
var (
67+
health string
68+
exitCode int
69+
)
70+
if inspect.State != nil {
71+
switch inspect.State.Status {
72+
case "running":
73+
if inspect.State.Health != nil {
74+
health = inspect.State.Health.Status
75+
}
76+
case "exited", "dead":
77+
exitCode = inspect.State.ExitCode
78+
}
6679
}
6780

6881
summary[i] = compose.ContainerSummary{
@@ -72,6 +85,7 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options com
7285
Service: container.Labels[serviceLabel],
7386
State: container.State,
7487
Health: health,
88+
ExitCode: exitCode,
7589
Publishers: publishers,
7690
}
7791
return nil

local/compose/ps_test.go

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ func TestPs(t *testing.T) {
4040
args := filters.NewArgs(projectFilter(testProject))
4141
args.Add("label", "com.docker.compose.oneoff=False")
4242
listOpts := apitypes.ContainerListOptions{Filters: args, All: true}
43-
c1, inspect1 := containerDetails("service1", "123", "Running", "healthy")
44-
c2, inspect2 := containerDetails("service1", "456", "Running", "")
43+
c1, inspect1 := containerDetails("service1", "123", "running", "healthy", 0)
44+
c2, inspect2 := containerDetails("service1", "456", "running", "", 0)
4545
c2.Ports = []apitypes.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}}
46-
c3, inspect3 := containerDetails("service2", "789", "Running", "")
46+
c3, inspect3 := containerDetails("service2", "789", "exited", "", 130)
4747
api.EXPECT().ContainerList(ctx, listOpts).Return([]apitypes.Container{c1, c2, c3}, nil)
4848
api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil)
4949
api.EXPECT().ContainerInspect(anyCancellableContext(), "456").Return(inspect2, nil)
@@ -52,45 +52,21 @@ func TestPs(t *testing.T) {
5252
containers, err := tested.Ps(ctx, testProject, compose.PsOptions{})
5353

5454
expected := []compose.ContainerSummary{
55-
{ID: "123", Name: "123", Project: testProject, Service: "service1", State: "Running", Health: "healthy", Publishers: nil},
56-
{ID: "456", Name: "456", Project: testProject, Service: "service1", State: "Running", Health: "", Publishers: []compose.PortPublisher{{URL: "localhost:80", TargetPort: 90, PublishedPort: 80}}},
57-
{ID: "789", Name: "789", Project: testProject, Service: "service2", State: "Running", Health: "", Publishers: nil},
55+
{ID: "123", Name: "123", Project: testProject, Service: "service1", State: "running", Health: "healthy", Publishers: nil},
56+
{ID: "456", Name: "456", Project: testProject, Service: "service1", State: "running", Health: "", Publishers: []compose.PortPublisher{{URL: "localhost:80", TargetPort: 90, PublishedPort: 80}}},
57+
{ID: "789", Name: "789", Project: testProject, Service: "service2", State: "exited", Health: "", ExitCode: 130, Publishers: nil},
5858
}
5959
assert.NilError(t, err)
6060
assert.DeepEqual(t, containers, expected)
6161
}
6262

63-
func TestPsAll(t *testing.T) {
64-
mockCtrl := gomock.NewController(t)
65-
defer mockCtrl.Finish()
66-
api := mocks.NewMockAPIClient(mockCtrl)
67-
tested.apiClient = api
68-
69-
ctx := context.Background()
70-
listOpts := apitypes.ContainerListOptions{Filters: filters.NewArgs(projectFilter(testProject)), All: true}
71-
c1, inspect1 := containerDetails("service1", "123", "Running", "healthy")
72-
c2, inspect2 := containerDetails("service1", "456", "Stopped", "")
73-
api.EXPECT().ContainerList(ctx, listOpts).Return([]apitypes.Container{c1, c2}, nil)
74-
api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil)
75-
api.EXPECT().ContainerInspect(anyCancellableContext(), "456").Return(inspect2, nil)
76-
77-
containers, err := tested.Ps(ctx, testProject, compose.PsOptions{All: true})
78-
79-
expected := []compose.ContainerSummary{
80-
{ID: "123", Name: "123", Project: testProject, Service: "service1", State: "Running", Health: "healthy", Publishers: nil},
81-
{ID: "456", Name: "456", Project: testProject, Service: "service1", State: "Stopped", Health: "", Publishers: nil},
82-
}
83-
assert.NilError(t, err)
84-
assert.DeepEqual(t, containers, expected)
85-
}
86-
87-
func containerDetails(service string, id string, status string, health string) (apitypes.Container, apitypes.ContainerJSON) {
63+
func containerDetails(service string, id string, status string, health string, exitCode int) (apitypes.Container, apitypes.ContainerJSON) {
8864
container := apitypes.Container{
8965
ID: id,
9066
Names: []string{"/" + id},
9167
Labels: containerLabels(service),
9268
State: status,
9369
}
94-
inspect := apitypes.ContainerJSON{ContainerJSONBase: &apitypes.ContainerJSONBase{State: &apitypes.ContainerState{Status: status, Health: &apitypes.Health{Status: health}}}}
70+
inspect := apitypes.ContainerJSON{ContainerJSONBase: &apitypes.ContainerJSONBase{State: &apitypes.ContainerState{Status: status, Health: &apitypes.Health{Status: health}, ExitCode: exitCode}}}
9571
return container, inspect
9672
}

0 commit comments

Comments
 (0)