in internal/components/setup/compose_provider.go [459:516]
func WaitPort(ctx context.Context, target wait.StrategyTarget, waitPort nat.Port, timeout time.Duration) (err error) {
// limit context to startupTimeout
ctx, cancelContext := context.WithTimeout(ctx, timeout)
defer cancelContext()
ipAddress, err := target.Host(ctx)
if err != nil {
return
}
var waitInterval = 100 * time.Millisecond
port, err := findMappedPort(ctx, target, waitPort)
proto := port.Proto()
portNumber := port.Int()
portString := strconv.Itoa(portNumber)
// external check
dialer := net.Dialer{}
address := net.JoinHostPort(ipAddress, portString)
for {
conn, err := dialer.DialContext(ctx, proto, address)
if err != nil {
if v, ok := err.(*net.OpError); ok {
if v2, ok := (v.Err).(*os.SyscallError); ok {
if isConnRefusedErr(v2.Err) {
time.Sleep(waitInterval)
continue
}
}
}
return err
}
conn.Close()
break
}
// internal check
command := buildInternalCheckCommand(waitPort.Int())
for {
if ctx.Err() != nil {
return ctx.Err()
}
exitCode, err := target.Exec(ctx, []string{"/bin/sh", "-c", command})
if err != nil {
return err
}
if exitCode == 0 {
break
} else if exitCode == 126 {
return errors.New("/bin/sh command not executable")
}
}
return nil
}