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
2 changes: 1 addition & 1 deletion pkg/api/dryrunclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (d *DryRunClient) ContainerInspect(ctx context.Context, container string) (
ID: id,
Name: container,
State: &containerType.State{
Status: "running", // needed for --wait option
Status: containerType.StateRunning, // needed for --wait option
Health: &containerType.Health{
Status: containerType.Healthy, // needed for healthcheck control
},
Expand Down
24 changes: 12 additions & 12 deletions pkg/compose/convergence.go
Original file line number Diff line number Diff line change
Expand Up @@ -828,46 +828,46 @@ func (s *composeService) getLinks(ctx context.Context, projectName string, servi

func (s *composeService) isServiceHealthy(ctx context.Context, containers Containers, fallbackRunning bool) (bool, error) {
for _, c := range containers {
container, err := s.apiClient().ContainerInspect(ctx, c.ID)
ctr, err := s.apiClient().ContainerInspect(ctx, c.ID)
if err != nil {
return false, err
}
name := container.Name[1:]
name := ctr.Name[1:]

if container.State.Status == "exited" {
return false, fmt.Errorf("container %s exited (%d)", name, container.State.ExitCode)
if ctr.State.Status == containerType.StateExited {
return false, fmt.Errorf("container %s exited (%d)", name, ctr.State.ExitCode)
}

if container.Config.Healthcheck == nil && fallbackRunning {
if ctr.Config.Healthcheck == nil && fallbackRunning {
// Container does not define a health check, but we can fall back to "running" state
return container.State != nil && container.State.Status == "running", nil
return ctr.State != nil && ctr.State.Status == containerType.StateRunning, nil
}

if container.State == nil || container.State.Health == nil {
if ctr.State == nil || ctr.State.Health == nil {
return false, fmt.Errorf("container %s has no healthcheck configured", name)
}
switch container.State.Health.Status {
switch ctr.State.Health.Status {
case containerType.Healthy:
// Continue by checking the next container.
case containerType.Unhealthy:
return false, fmt.Errorf("container %s is unhealthy", name)
case containerType.Starting:
return false, nil
default:
return false, fmt.Errorf("container %s had unexpected health status %q", name, container.State.Health.Status)
return false, fmt.Errorf("container %s had unexpected health status %q", name, ctr.State.Health.Status)
}
}
return true, nil
}

func (s *composeService) isServiceCompleted(ctx context.Context, containers Containers) (bool, int, error) {
for _, c := range containers {
container, err := s.apiClient().ContainerInspect(ctx, c.ID)
ctr, err := s.apiClient().ContainerInspect(ctx, c.ID)
if err != nil {
return false, 0, err
}
if container.State != nil && container.State.Status == "exited" {
return true, container.State.ExitCode, nil
if ctr.State != nil && ctr.State.Status == containerType.StateExited {
return true, ctr.State.ExitCode, nil
}
}
return false, 0, nil
Expand Down
51 changes: 26 additions & 25 deletions pkg/compose/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"sort"
"strings"

"github.com/docker/docker/api/types/container"
"golang.org/x/sync/errgroup"

"github.com/docker/compose/v2/pkg/api"
Expand All @@ -42,13 +43,13 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
}
summary := make([]api.ContainerSummary, len(containers))
eg, ctx := errgroup.WithContext(ctx)
for i, container := range containers {
for i, ctr := range containers {
eg.Go(func() error {
publishers := make([]api.PortPublisher, len(container.Ports))
sort.Slice(container.Ports, func(i, j int) bool {
return container.Ports[i].PrivatePort < container.Ports[j].PrivatePort
publishers := make([]api.PortPublisher, len(ctr.Ports))
sort.Slice(ctr.Ports, func(i, j int) bool {
return ctr.Ports[i].PrivatePort < ctr.Ports[j].PrivatePort
})
for i, p := range container.Ports {
for i, p := range ctr.Ports {
publishers[i] = api.PortPublisher{
URL: p.IP,
TargetPort: int(p.PrivatePort),
Expand All @@ -57,22 +58,22 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
}
}

inspect, err := s.apiClient().ContainerInspect(ctx, container.ID)
inspect, err := s.apiClient().ContainerInspect(ctx, ctr.ID)
if err != nil {
return err
}

var (
health string
health container.HealthStatus
exitCode int
)
if inspect.State != nil {
switch inspect.State.Status {
case "running":
case container.StateRunning:
if inspect.State.Health != nil {
health = inspect.State.Health.Status
}
case "exited", "dead":
case container.StateExited, container.StateDead:
exitCode = inspect.State.ExitCode
}
}
Expand All @@ -81,7 +82,7 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
local int
mounts []string
)
for _, m := range container.Mounts {
for _, m := range ctr.Mounts {
name := m.Name
if name == "" {
name = m.Source
Expand All @@ -93,26 +94,26 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
}

var networks []string
if container.NetworkSettings != nil {
for k := range container.NetworkSettings.Networks {
if ctr.NetworkSettings != nil {
for k := range ctr.NetworkSettings.Networks {
networks = append(networks, k)
}
}

summary[i] = api.ContainerSummary{
ID: container.ID,
Name: getCanonicalContainerName(container),
Names: container.Names,
Image: container.Image,
Project: container.Labels[api.ProjectLabel],
Service: container.Labels[api.ServiceLabel],
Command: container.Command,
State: container.State,
Status: container.Status,
Created: container.Created,
Labels: container.Labels,
SizeRw: container.SizeRw,
SizeRootFs: container.SizeRootFs,
ID: ctr.ID,
Name: getCanonicalContainerName(ctr),
Names: ctr.Names,
Image: ctr.Image,
Project: ctr.Labels[api.ProjectLabel],
Service: ctr.Labels[api.ServiceLabel],
Command: ctr.Command,
State: ctr.State,
Status: ctr.Status,
Created: ctr.Created,
Labels: ctr.Labels,
SizeRw: ctr.SizeRw,
SizeRootFs: ctr.SizeRootFs,
Mounts: mounts,
LocalVolumes: local,
Networks: networks,
Expand Down
26 changes: 16 additions & 10 deletions pkg/compose/ps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import (
"testing"

containerType "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"go.uber.org/mock/gomock"
"gotest.tools/v3/assert"

compose "github.com/docker/compose/v2/pkg/api"
"github.com/docker/docker/api/types/filters"
)

func TestPs(t *testing.T) {
Expand All @@ -42,10 +42,10 @@ func TestPs(t *testing.T) {
args := filters.NewArgs(projectFilter(strings.ToLower(testProject)), hasConfigHashLabel())
args.Add("label", "com.docker.compose.oneoff=False")
listOpts := containerType.ListOptions{Filters: args, All: false}
c1, inspect1 := containerDetails("service1", "123", "running", "healthy", 0)
c2, inspect2 := containerDetails("service1", "456", "running", "", 0)
c1, inspect1 := containerDetails("service1", "123", containerType.StateRunning, containerType.Healthy, 0)
c2, inspect2 := containerDetails("service1", "456", containerType.StateRunning, "", 0)
c2.Ports = []containerType.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}}
c3, inspect3 := containerDetails("service2", "789", "exited", "", 130)
c3, inspect3 := containerDetails("service2", "789", containerType.StateExited, "", 130)
api.EXPECT().ContainerList(ctx, listOpts).Return([]containerType.Summary{c1, c2, c3}, nil)
api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil)
api.EXPECT().ContainerInspect(anyCancellableContext(), "456").Return(inspect2, nil)
Expand All @@ -56,7 +56,9 @@ func TestPs(t *testing.T) {
expected := []compose.ContainerSummary{
{
ID: "123", Name: "123", Names: []string{"/123"}, Image: "foo", Project: strings.ToLower(testProject), Service: "service1",
State: "running", Health: "healthy", Publishers: []compose.PortPublisher{},
State: containerType.StateRunning,
Health: containerType.Healthy,
Publishers: []compose.PortPublisher{},
Labels: map[string]string{
compose.ProjectLabel: strings.ToLower(testProject),
compose.ConfigFilesLabel: "/src/pkg/compose/testdata/compose.yaml",
Expand All @@ -66,7 +68,8 @@ func TestPs(t *testing.T) {
},
{
ID: "456", Name: "456", Names: []string{"/456"}, Image: "foo", Project: strings.ToLower(testProject), Service: "service1",
State: "running", Health: "",
State: containerType.StateRunning,
Health: "",
Publishers: []compose.PortPublisher{{URL: "localhost", TargetPort: 90, PublishedPort: 80}},
Labels: map[string]string{
compose.ProjectLabel: strings.ToLower(testProject),
Expand All @@ -77,7 +80,10 @@ func TestPs(t *testing.T) {
},
{
ID: "789", Name: "789", Names: []string{"/789"}, Image: "foo", Project: strings.ToLower(testProject), Service: "service2",
State: "exited", Health: "", ExitCode: 130, Publishers: []compose.PortPublisher{},
State: containerType.StateExited,
Health: "",
ExitCode: 130,
Publishers: []compose.PortPublisher{},
Labels: map[string]string{
compose.ProjectLabel: strings.ToLower(testProject),
compose.ConfigFilesLabel: "/src/pkg/compose/testdata/compose.yaml",
Expand All @@ -90,8 +96,8 @@ func TestPs(t *testing.T) {
assert.DeepEqual(t, containers, expected)
}

func containerDetails(service string, id string, status string, health string, exitCode int) (containerType.Summary, containerType.InspectResponse) {
container := containerType.Summary{
func containerDetails(service string, id string, status containerType.ContainerState, health containerType.HealthStatus, exitCode int) (containerType.Summary, containerType.InspectResponse) {
ctr := containerType.Summary{
ID: id,
Names: []string{"/" + id},
Image: "foo",
Expand All @@ -107,5 +113,5 @@ func containerDetails(service string, id string, status string, health string, e
},
},
}
return container, inspect
return ctr, inspect
}
Loading