in internal/pkg/docker/orchestrator/orchestrator.go [490:552]
func (o *Orchestrator) waitForContainerDependencies(ctx context.Context, name string, definitions map[string]ContainerDefinition) error {
var deps []string
for depName, state := range definitions[name].DependsOn {
deps = append(deps, fmt.Sprintf("%s->%s", depName, state))
}
logMsg := strings.Join(deps, ", ")
fmt.Printf("Waiting for container %q dependencies: [%s]\n", name, color.Emphasize(logMsg))
eg, ctx := errgroup.WithContext(ctx)
for name, state := range definitions[name].DependsOn {
name, state := name, state
eg.Go(func() error {
ctrId := o.containerID(name)
ticker := time.NewTicker(700 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ticker.C:
case <-ctx.Done():
return ctx.Err()
}
switch state {
case ctrStateStart:
return nil
case ctrStateHealthy:
healthy, err := o.docker.IsContainerHealthy(ctx, ctrId)
if err != nil {
return fmt.Errorf("wait for container %q to be healthy: %w", ctrId, err)
}
if healthy {
log.Successf("Successfully dependency container %q reached healthy\n", ctrId)
return nil
}
case ctrStateComplete:
exitCode, err := o.docker.ContainerExitCode(ctx, ctrId)
var errContainerNotExited *dockerengine.ErrContainerNotExited
if errors.As(err, &errContainerNotExited) {
continue
}
if err != nil {
return fmt.Errorf("wait for container %q to complete: %w", ctrId, err)
}
log.Successf("%q's dependency container %q exited with code: %d\n", name, ctrId, exitCode)
return nil
case ctrStateSuccess:
exitCode, err := o.docker.ContainerExitCode(ctx, ctrId)
var errContainerNotExited *dockerengine.ErrContainerNotExited
if errors.As(err, &errContainerNotExited) {
continue
}
if err != nil {
return fmt.Errorf("wait for container %q to success: %w", ctrId, err)
}
if exitCode != 0 {
return fmt.Errorf("dependency container %q exited with non-zero exit code %d", ctrId, exitCode)
}
log.Successf("%q's dependency container %q exited with code: %d\n", name, ctrId, exitCode)
return nil
}
}
})
}
return eg.Wait()
}