cmd: support caddy start on IPv6-only hosts (#7744)
parent
408d20a0e5
commit
6628c4a9de
|
|
@ -58,7 +58,7 @@ func cmdStart(fl Flags) (int, error) {
|
|||
|
||||
// open a listener to which the child process will connect when
|
||||
// it is ready to confirm that it has successfully started
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ln, err := listenTCPForPingback(net.Listen)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("opening listener for success confirmation: %v", err)
|
||||
|
|
@ -169,6 +169,22 @@ func cmdStart(fl Flags) (int, error) {
|
|||
return caddy.ExitCodeSuccess, nil
|
||||
}
|
||||
|
||||
type tcpListenFunc func(network, address string) (net.Listener, error)
|
||||
|
||||
func listenTCPForPingback(listen tcpListenFunc) (net.Listener, error) {
|
||||
ln, ipv4Err := listen("tcp4", "127.0.0.1:0")
|
||||
if ipv4Err == nil {
|
||||
return ln, nil
|
||||
}
|
||||
|
||||
ln, ipv6Err := listen("tcp6", "[::1]:0")
|
||||
if ipv6Err == nil {
|
||||
return ln, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("listen on 127.0.0.1:0: %v; listen on [::1]:0: %v", ipv4Err, ipv6Err)
|
||||
}
|
||||
|
||||
func cmdRun(fl Flags) (int, error) {
|
||||
caddy.TrapSignals()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package caddycmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
|
@ -169,6 +171,80 @@ here"
|
|||
}
|
||||
}
|
||||
|
||||
func TestListenTCPForPingbackUsesIPv4Loopback(t *testing.T) {
|
||||
var calls []string
|
||||
expected := &stubListener{addr: &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 1234}}
|
||||
|
||||
actual, err := listenTCPForPingback(func(network, address string) (net.Listener, error) {
|
||||
calls = append(calls, network+" "+address)
|
||||
return expected, nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("listenTCPForPingback returned error: %v", err)
|
||||
}
|
||||
if actual != expected {
|
||||
t.Fatalf("expected listener %p, got %p", expected, actual)
|
||||
}
|
||||
|
||||
expectCalls := []string{"tcp4 127.0.0.1:0"}
|
||||
if !reflect.DeepEqual(calls, expectCalls) {
|
||||
t.Fatalf("expected calls %v, got %v", expectCalls, calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListenTCPForPingbackFallsBackToIPv6Loopback(t *testing.T) {
|
||||
var calls []string
|
||||
expected := &stubListener{addr: &net.TCPAddr{IP: net.ParseIP("::1"), Port: 1234}}
|
||||
|
||||
actual, err := listenTCPForPingback(func(network, address string) (net.Listener, error) {
|
||||
calls = append(calls, network+" "+address)
|
||||
if len(calls) == 1 {
|
||||
return nil, errors.New("ipv4 unavailable")
|
||||
}
|
||||
return expected, nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("listenTCPForPingback returned error: %v", err)
|
||||
}
|
||||
if actual != expected {
|
||||
t.Fatalf("expected listener %p, got %p", expected, actual)
|
||||
}
|
||||
|
||||
expectCalls := []string{"tcp4 127.0.0.1:0", "tcp6 [::1]:0"}
|
||||
if !reflect.DeepEqual(calls, expectCalls) {
|
||||
t.Fatalf("expected calls %v, got %v", expectCalls, calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListenTCPForPingbackReportsBothFailures(t *testing.T) {
|
||||
_, err := listenTCPForPingback(func(network, address string) (net.Listener, error) {
|
||||
return nil, errors.New(network + " failed")
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "tcp4 failed") ||
|
||||
!strings.Contains(err.Error(), "tcp6 failed") {
|
||||
t.Fatalf("expected both listener errors, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type stubListener struct {
|
||||
addr net.Addr
|
||||
}
|
||||
|
||||
func (sl *stubListener) Accept() (net.Conn, error) {
|
||||
return nil, net.ErrClosed
|
||||
}
|
||||
|
||||
func (sl *stubListener) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sl *stubListener) Addr() net.Addr {
|
||||
return sl.addr
|
||||
}
|
||||
|
||||
func Test_isCaddyfile(t *testing.T) {
|
||||
type args struct {
|
||||
configFile string
|
||||
|
|
|
|||
Loading…
Reference in New Issue