diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go index 5ad3c94b1..4f90cda99 100644 --- a/pkg/compose/convergence.go +++ b/pkg/compose/convergence.go @@ -364,7 +364,12 @@ func containerReasonEvents(containers Containers, eventFunc func(string, string) const ServiceConditionRunningOrHealthy = "running_or_healthy" //nolint:gocyclo -func (s *composeService) waitDependencies(ctx context.Context, project *types.Project, dependant string, dependencies types.DependsOnConfig, containers Containers) error { +func (s *composeService) waitDependencies(ctx context.Context, project *types.Project, dependant string, dependencies types.DependsOnConfig, containers Containers, timeout time.Duration) error { + if timeout > 0 { + withTimeout, cancelFunc := context.WithTimeout(ctx, timeout) + defer cancelFunc() + ctx = withTimeout + } eg, _ := errgroup.WithContext(ctx) w := progress.ContextWriter(ctx) for dep, config := range dependencies { @@ -454,7 +459,11 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr } }) } - return eg.Wait() + err := eg.Wait() + if errors.Is(err, context.DeadlineExceeded) { + return fmt.Errorf("timeout waiting for dependencies") + } + return err } func shouldWaitForDependency(serviceName string, dependencyConfig types.ServiceDependency, project *types.Project) (bool, error) { @@ -760,12 +769,12 @@ func (s *composeService) isServiceCompleted(ctx context.Context, containers Cont return false, 0, nil } -func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig, containers Containers) error { +func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig, containers Containers, timeout time.Duration) error { if service.Deploy != nil && service.Deploy.Replicas != nil && *service.Deploy.Replicas == 0 { return nil } - err := s.waitDependencies(ctx, project, service.Name, service.DependsOn, containers) + err := s.waitDependencies(ctx, project, service.Name, service.DependsOn, containers, timeout) if err != nil { return err } diff --git a/pkg/compose/convergence_test.go b/pkg/compose/convergence_test.go index e25ccd9f6..dc981fdaf 100644 --- a/pkg/compose/convergence_test.go +++ b/pkg/compose/convergence_test.go @@ -239,7 +239,7 @@ func TestWaitDependencies(t *testing.T) { "db": {Condition: ServiceConditionRunningOrHealthy}, "redis": {Condition: ServiceConditionRunningOrHealthy}, } - assert.NilError(t, tested.waitDependencies(context.Background(), &project, "", dependencies, nil)) + assert.NilError(t, tested.waitDependencies(context.Background(), &project, "", dependencies, nil, 0)) }) t.Run("should skip dependencies with condition service_started", func(t *testing.T) { dbService := types.ServiceConfig{Name: "db", Scale: intPtr(1)} @@ -252,7 +252,7 @@ func TestWaitDependencies(t *testing.T) { "db": {Condition: types.ServiceConditionStarted, Required: true}, "redis": {Condition: types.ServiceConditionStarted, Required: true}, } - assert.NilError(t, tested.waitDependencies(context.Background(), &project, "", dependencies, nil)) + assert.NilError(t, tested.waitDependencies(context.Background(), &project, "", dependencies, nil, 0)) }) } diff --git a/pkg/compose/run.go b/pkg/compose/run.go index cdafb4b8a..1bd769dbb 100644 --- a/pkg/compose/run.go +++ b/pkg/compose/run.go @@ -93,7 +93,7 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project, } if !opts.NoDeps { - if err := s.waitDependencies(ctx, project, service.Name, service.DependsOn, observedState); err != nil { + if err := s.waitDependencies(ctx, project, service.Name, service.DependsOn, observedState, 0); err != nil { return "", err } } diff --git a/pkg/compose/start.go b/pkg/compose/start.go index 7caeb3057..b5fcceebf 100644 --- a/pkg/compose/start.go +++ b/pkg/compose/start.go @@ -129,7 +129,7 @@ func (s *composeService) start(ctx context.Context, projectName string, options return err } - return s.startService(ctx, project, service, containers) + return s.startService(ctx, project, service, containers, options.WaitTimeout) }) if err != nil { return err @@ -149,7 +149,7 @@ func (s *composeService) start(ctx context.Context, projectName string, options defer cancel() } - err = s.waitDependencies(ctx, project, project.Name, depends, containers) + err = s.waitDependencies(ctx, project, project.Name, depends, containers, 0) if err != nil { if errors.Is(ctx.Err(), context.DeadlineExceeded) { return fmt.Errorf("application not healthy after %s", options.WaitTimeout)