Skip to content

Commit

Permalink
wait on service containers as dependencies to be deterministic
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <[email protected]>
  • Loading branch information
ndeloof committed Jan 27, 2023
1 parent 79361a5 commit e44520e
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 19 deletions.
28 changes: 15 additions & 13 deletions pkg/compose/convergence.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
<-ticker.C
switch config.Condition {
case ServiceConditionRunningOrHealthy:
healthy, err := s.isServiceHealthy(ctx, containers, dep, true)
healthy, err := s.isServiceHealthy(ctx, containers, true)
if err != nil {
return err
}
Expand All @@ -310,7 +310,7 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
return nil
}
case types.ServiceConditionHealthy:
healthy, err := s.isServiceHealthy(ctx, containers, dep, false)
healthy, err := s.isServiceHealthy(ctx, containers, false)
if err != nil {
w.Events(containerEvents(containers, progress.ErrorEvent))
return errors.Wrap(err, "dependency failed to start")
Expand All @@ -320,7 +320,7 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
return nil
}
case types.ServiceConditionCompletedSuccessfully:
exited, code, err := s.isServiceCompleted(ctx, containers, dep)
exited, code, err := s.isServiceCompleted(ctx, containers)
if err != nil {
return err
}
Expand Down Expand Up @@ -641,7 +641,7 @@ func (s *composeService) connectContainerToNetwork(ctx context.Context, id strin
return nil
}

func (s *composeService) isServiceHealthy(ctx context.Context, containers Containers, service string, fallbackRunning bool) (bool, error) {
func (s *composeService) isServiceHealthy(ctx context.Context, containers Containers, fallbackRunning bool) (bool, error) {
if len(containers) == 0 {
return false, nil
}
Expand All @@ -650,33 +650,35 @@ func (s *composeService) isServiceHealthy(ctx context.Context, containers Contai
if err != nil {
return false, err
}
name := container.Name[1:]

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

if container.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
}

if container.State.Status == "exited" {
return false, fmt.Errorf("container for service %q exited (%d)", service, container.State.ExitCode)
}

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

func (s *composeService) isServiceCompleted(ctx context.Context, containers Containers, dep string) (bool, int, error) {
func (s *composeService) isServiceCompleted(ctx context.Context, containers Containers) (bool, int, error) {
for _, c := range containers {
container, err := s.apiClient().ContainerInspect(ctx, c.ID)
if err != nil {
Expand Down Expand Up @@ -707,7 +709,7 @@ func (s *composeService) startService(ctx context.Context, project *types.Projec
}

w := progress.ContextWriter(ctx)
for _, container := range containers {
for _, container := range containers.filter(isService(service.Name)) {
if container.State == ContainerRunning {
continue
}
Expand Down
12 changes: 6 additions & 6 deletions pkg/compose/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ package compose

import (
"context"
"github.com/docker/docker/api/types/filters"
"strings"
"time"

"github.com/compose-spec/compose-go/types"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"

"github.com/compose-spec/compose-go/types"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"

"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
)

func (s *composeService) Start(ctx context.Context, projectName string, options api.StartOptions) error {
Expand Down Expand Up @@ -86,7 +86,7 @@ func (s *composeService) start(ctx context.Context, projectName string, options
return err
}

return s.startService(ctx, project, service, containers.filter(isService(service.Name)))
return s.startService(ctx, project, service, containers)
})
if err != nil {
return err
Expand Down

0 comments on commit e44520e

Please sign in to comment.