mirror of
https://github.com/traefik/traefik.git
synced 2025-08-07 15:17:09 +02:00
Fix tcp health check tests
This commit is contained in:
parent
7f33218331
commit
6a53b26517
@ -101,7 +101,7 @@ func (thc *ServiceTCPHealthChecker) Check(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (thc *ServiceTCPHealthChecker) executeHealthCheck(ctx context.Context, config *dynamic.TCPServerHealthCheck, target *net.TCPAddr) error {
|
func (thc *ServiceTCPHealthChecker) executeHealthCheck(_ context.Context, config *dynamic.TCPServerHealthCheck, target *net.TCPAddr) error {
|
||||||
dialer, err := thc.dialerManager.Get(config.ServersTransport, config.TLS)
|
dialer, err := thc.dialerManager.Get(config.ServersTransport, config.TLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -122,6 +122,7 @@ func (thc *ServiceTCPHealthChecker) executeHealthCheck(ctx context.Context, conf
|
|||||||
|
|
||||||
if config.Expected != "" {
|
if config.Expected != "" {
|
||||||
buf := make([]byte, len(config.Expected))
|
buf := make([]byte, len(config.Expected))
|
||||||
|
conn.SetReadDeadline(time.Now().Add(thc.timeout))
|
||||||
_, err = conn.Read(buf)
|
_, err = conn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -3,14 +3,15 @@ package healthcheck
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
ptypes "github.com/traefik/paerser/types"
|
ptypes "github.com/traefik/paerser/types"
|
||||||
@ -21,35 +22,52 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
|
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||||
MIICDDCCAXWgAwIBAgIQH20JmcOlcRWHNuf62SYwszANBgkqhkiG9w0BAQsFADAS
|
MIIDJzCCAg+gAwIBAgIUe3vnWg3cTbflL6kz2TyPUxmV8Y4wDQYJKoZIhvcNAQEL
|
||||||
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wIBcNMjUwMzA1MjAwOTM4WhgPMjA1
|
||||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
NTAyMjYyMDA5MzhaMBYxFDASBgNVBAMMC2V4YW1wbGUuY29tMIIBIjANBgkqhkiG
|
||||||
iQKBgQC0qINy3F4oq6viDnlpDDE5J08iSRGggg6EylJKBKZfphEG2ufgK78Dufl3
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4Mm4Sp6xzJvFZJWAv/KVmI1krywiuef8Fhlf
|
||||||
+7b0LlEY2AeZHwviHODqC9a6ihj1ZYQk0/djAh+OeOhFEWu+9T/VP8gVFarFqT8D
|
JR2M0caKixjBcNt4U8KwrzIrqL+8nilbps1QuwpQ09+6ztlbUXUL6DqR8ZC+4oCp
|
||||||
Opy+hrG7YJivUIzwb4fmJQRI7FajzsnGyM6LiXLU+0qzb7ZO/QIDAQABo2EwXzAO
|
gOZ3yyVX2vhMigkATbQyJrX/WVjWSHD5rIUBP2BrsaYLt1qETnFP9wwQ3YEi7V4l
|
||||||
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
c4+jDrZOtJvrv+tRClt9gQJVgkr7Y30X+dx+rsh+ROaA2+/VTDX0qtoqd/4fjhcJ
|
||||||
AwEB/zAnBgNVHREEIDAeggtleGFtcGxlLmNvbYIPd3d3LmV4YW1wbGUuY29tMA0G
|
OY9VLm0eU66VUMyOTNeUm6ZAXRBp/EonIM1FXOlj82S0pZQbPrvyWWqWoAjtPvLU
|
||||||
CSqGSIb3DQEBCwUAA4GBAB+eluoQYzyyMfeEEAOtlldevx5MtDENT05NB0WI+91R
|
qRzqp/BQJqx3EHz1dP6s+xUjP999B+7jhiHoFhZ/bfVVlx8XkwIDAQABo2swaTAd
|
||||||
we7mX8lv763u0XuCWPxbHszhclI6FFjoQef0Z1NYLRm8ZRq58QqWDFZ3E6wdDK+B
|
BgNVHQ4EFgQUhJiJ37LW6RODCpBPAApG1zQxFtAwHwYDVR0jBBgwFoAUhJiJ37LW
|
||||||
+OWvkW+hRavo6R9LzIZPfbv8yBo4M9PK/DXw8hLqH7VkkI+Gh793iH7Ugd4A7wvT
|
6RODCpBPAApG1zQxFtAwDwYDVR0TAQH/BAUwAwEB/zAWBgNVHREEDzANggtleGFt
|
||||||
|
cGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAfnDPHllA1TFlQ6zY46tqM20d68bR
|
||||||
|
kXeGMKLoaATFPbDea5H8/GM5CU6CPD7RUuEB9CvxvaM0aOInxkgstozG7BOr8hcs
|
||||||
|
WS9fMgM0oO5yGiSOv+Qa0Rc0BFb6A1fUJRta5MI5DTdTJLoyoRX/5aocSI34T67x
|
||||||
|
ULbkJvVXw6hnx/KZ65apNobfmVQSy7DR8Fo82eB4hSoaLpXyUUTLmctGgrRCoKof
|
||||||
|
GVUJfKsDJ4Ts8WIR1np74flSoxksWSHEOYk79AZOPANYgJwPMMiiZKsKm17GBoGu
|
||||||
|
DxI0om4eX8GaSSZAtG6TOt3O3v1oCjKNsAC+u585HN0x0MFA33TUzC15NA==
|
||||||
-----END CERTIFICATE-----`)
|
-----END CERTIFICATE-----`)
|
||||||
|
|
||||||
// LocalhostKey is the private key for localhostCert.
|
|
||||||
var LocalhostKey = []byte(`-----BEGIN PRIVATE KEY-----
|
var LocalhostKey = []byte(`-----BEGIN PRIVATE KEY-----
|
||||||
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALSog3LcXiirq+IO
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDgybhKnrHMm8Vk
|
||||||
eWkMMTknTyJJEaCCDoTKUkoEpl+mEQba5+ArvwO5+Xf7tvQuURjYB5kfC+Ic4OoL
|
lYC/8pWYjWSvLCK55/wWGV8lHYzRxoqLGMFw23hTwrCvMiuov7yeKVumzVC7ClDT
|
||||||
1rqKGPVlhCTT92MCH4546EURa771P9U/yBUVqsWpPwM6nL6GsbtgmK9QjPBvh+Yl
|
37rO2VtRdQvoOpHxkL7igKmA5nfLJVfa+EyKCQBNtDImtf9ZWNZIcPmshQE/YGux
|
||||||
BEjsVqPOycbIzouJctT7SrNvtk79AgMBAAECgYB1wMT1MBgbkFIXpXGTfAP1id61
|
pgu3WoROcU/3DBDdgSLtXiVzj6MOtk60m+u/61EKW32BAlWCSvtjfRf53H6uyH5E
|
||||||
rUTVBxCpkypx3ngHLjo46qRq5Hi72BN4FlTY8fugIudI8giP2FztkMvkiLDc4m0p
|
5oDb79VMNfSq2ip3/h+OFwk5j1UubR5TrpVQzI5M15SbpkBdEGn8SicgzUVc6WPz
|
||||||
Gn+QMJzjlBjjTuNLvLy4aSmNRLIC3mtbx9PdU71DQswEpJHFj/vmsxbuSrG1I1YE
|
ZLSllBs+u/JZapagCO0+8tSpHOqn8FAmrHcQfPV0/qz7FSM/330H7uOGIegWFn9t
|
||||||
r1reuSo2ow6fOAjXLQJBANpz+RkOiPSPuvl+gi1sp2pLuynUJVDVqWZi386YRpfg
|
9VWXHxeTAgMBAAECggEALinfGhv7Iaz/3cdCOKlGBZ1MBxmGTC2TPKqbOpEWAWLH
|
||||||
DiKCLpqwqYDkOozm/fwFALvwXKGmsyyL43HO8eI+2NsCQQDTtY32V+02GPecdsyq
|
wwcjetznmjQKewBPrQkrYEPYGapioPbeYJS61Y4XzeO+vUOCA10ZhoSrytgJ1ANo
|
||||||
msK06EPVTSaYwj9Mm+q709KsmYFHLXDqXjcKV4UgKYKRPz7my1fXodMmGmfuh1a3
|
RoTlmxd8I3kVL5QCy8ONxjTFYaOy/OP9We9iypXhRAbLSE4HDKZfmOXTxSbDctql
|
||||||
/HMHAkEAmOQKN0tA90mRJwUvvvMIyRBv0fq0kzq28P3KfiF9ZtZdjjFmxMVYHOmf
|
Kq7uV3LX1KCfr9C6M8d79a0Rdr4p8IXp8MOg3tXq6n75vZbepRFyAujhg7o/kkTp
|
||||||
QPZ6VGR7+w1jB5BQXqEZcpHQIPSzeQJBAIy9tZJ/AYNlNbcegxEnsSjy/6VdlLsY
|
lgv87h89lrK97K+AjqtvCIT3X3VXfA+LYp3AoQFdOluKgyJT221MyHkTeI/7gggt
|
||||||
51vWi0Yym2uC4R6gZuBnoc+OP0ISVmqY0Qg9RjhjrCs4gr9f2ZaWjSECQCxqZMq1
|
Z57lVGD71UJH/LGUJWrraJqXd9uDxZWprD/s66BIAQKBgQD8CtHUJ/VuS7gP0ebN
|
||||||
3viJ8BGCC0m/5jv1EHur3YgwphYCkf4Li6DKwIdMLk1WXkTcPIY3V2Jqj8rPEB5V
|
688zrmRtENj6Gqi+URm/Pwgr9b7wKKlf9jjhg5F/ue+BgB7/nK6N7yJ4Xx3JJ5ox
|
||||||
rqPRSAtd/h6oZbs=
|
LqsRGLFa4fDBxogF/FN27obD8naOxe2wS1uTjM6LSrvdJ+HjeNEwHYhjuDjTAHj5
|
||||||
|
VVEMagZWgkE4jBiFUYefiYLsAQKBgQDkUVdW8cXaYri5xxDW86JNUzI1tUPyd6I+
|
||||||
|
AkOHV/V0y2zpwTHVLcETRpdVGpc5TH3J5vWf+5OvSz6RDTGjv7blDb8vB/kVkFmn
|
||||||
|
uXTi0dB9P+SYTsm+X3V7hOAFsyVYZ1D9IFsKUyMgxMdF+qgERjdPKx5IdLV/Jf3q
|
||||||
|
P9pQ922TkwKBgCKllhyU9Z8Y14+NKi4qeUxAb9uyUjFnUsT+vwxULNpmKL44yLfB
|
||||||
|
UCZoAKtPMwZZR2mZ70Dhm5pycNTDFeYm5Ssvesnkf0UT9oTkH9EcjvgGr5eGy9rN
|
||||||
|
MSSCWa46MsL/BYVQiWkU1jfnDiCrUvXrbX3IYWCo/TA5yfEhuQQMUiwBAoGADyzo
|
||||||
|
5TqEsBNHu/FjSSZAb2tMNw2pSoBxJDX6TxClm/G5d4AD0+uKncFfZaSy0HgpFDZp
|
||||||
|
tQx/sHML4ZBC8GNZwLe9MV8SS0Cg9Oj6v+i6Ntj8VLNH7YNix6b5TOevX8TeOTTh
|
||||||
|
WDpWZ2Ms65XRfRc9reFrzd0UAzN/QQaleCQ6AEkCgYBe4Ucows7JGbv7fNkz3nb1
|
||||||
|
kyH+hk9ecnq/evDKX7UUxKO1wwTi74IYKgcRB2uPLpHKL35gPz+LAfCphCW5rwpR
|
||||||
|
lvDhS+Pi/1KCBJxLHMv+V/WrckDRgHFnAhDaBZ+2vI/s09rKDnpjcTzV7x22kL0b
|
||||||
|
XIJCEEE8JZ4AXIZ+IcB6LA==
|
||||||
-----END PRIVATE KEY-----`)
|
-----END PRIVATE KEY-----`)
|
||||||
|
|
||||||
// openssl req -newkey rsa:2048 \
|
// openssl req -newkey rsa:2048 \
|
||||||
@ -109,8 +127,6 @@ ajIPbTY+Fe9OTOFTN48ujXNn
|
|||||||
-----END PRIVATE KEY-----`)
|
-----END PRIVATE KEY-----`)
|
||||||
|
|
||||||
func Test_ServiceTCPHealthChecker_Check(t *testing.T) {
|
func Test_ServiceTCPHealthChecker_Check(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
server *sequencedTcpServer
|
server *sequencedTcpServer
|
||||||
@ -192,10 +208,12 @@ func Test_ServiceTCPHealthChecker_Check(t *testing.T) {
|
|||||||
desc: "healthy server with TLS certificate",
|
desc: "healthy server with TLS certificate",
|
||||||
server: newTCPServer(t,
|
server: newTCPServer(t,
|
||||||
true,
|
true,
|
||||||
tcpMockSequence{accept: true},
|
tcpMockSequence{accept: true, payloadIn: "request", payloadOut: "response"},
|
||||||
tcpMockSequence{accept: true},
|
tcpMockSequence{accept: true, payloadIn: "request", payloadOut: "response"},
|
||||||
),
|
),
|
||||||
config: &dynamic.TCPServerHealthCheck{
|
config: &dynamic.TCPServerHealthCheck{
|
||||||
|
Payload: "request",
|
||||||
|
Expected: "response",
|
||||||
Interval: ptypes.Duration(time.Millisecond * 100),
|
Interval: ptypes.Duration(time.Millisecond * 100),
|
||||||
Timeout: ptypes.Duration(time.Millisecond * 99),
|
Timeout: ptypes.Duration(time.Millisecond * 99),
|
||||||
TLS: true,
|
TLS: true,
|
||||||
@ -209,9 +227,8 @@ func Test_ServiceTCPHealthChecker_Check(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
c, cancel := context.WithCancel(context.Background())
|
||||||
|
ctx := log.Logger.WithContext(c)
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer t.Cleanup(cancel)
|
defer t.Cleanup(cancel)
|
||||||
|
|
||||||
test.server.Start(t)
|
test.server.Start(t)
|
||||||
@ -227,6 +244,7 @@ func Test_ServiceTCPHealthChecker_Check(t *testing.T) {
|
|||||||
dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {
|
dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {
|
||||||
TLS: &dynamic.TLSClientConfig{
|
TLS: &dynamic.TLSClientConfig{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "example.com",
|
||||||
},
|
},
|
||||||
}})
|
}})
|
||||||
service := NewServiceTCPHealthChecker(dialerManager, &MetricsMock{gauge}, test.config, lb, serviceInfo, targets, "serviceName")
|
service := NewServiceTCPHealthChecker(dialerManager, &MetricsMock{gauge}, test.config, lb, serviceInfo, targets, "serviceName")
|
||||||
@ -263,7 +281,9 @@ type sequencedTcpServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newTCPServer(t *testing.T, tlsEnabled bool, statusSequence ...tcpMockSequence) *sequencedTcpServer {
|
func newTCPServer(t *testing.T, tlsEnabled bool, statusSequence ...tcpMockSequence) *sequencedTcpServer {
|
||||||
listener, err := net.ListenTCP("tcp", net.TCPAddrFromAddrPort(netip.MustParseAddrPort("127.0.0.1:0")))
|
addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
|
||||||
|
require.NoError(t, err)
|
||||||
|
listener, err := net.ListenTCP("tcp", addr)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tcpAddr, ok := listener.Addr().(*net.TCPAddr)
|
tcpAddr, ok := listener.Addr().(*net.TCPAddr)
|
||||||
@ -287,57 +307,76 @@ func (s *sequencedTcpServer) Start(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
var listener net.Listener
|
||||||
|
|
||||||
for _, seq := range s.StatusSequence {
|
for _, seq := range s.StatusSequence {
|
||||||
<-s.release
|
<-s.release
|
||||||
|
if listener != nil {
|
||||||
|
listener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
if !seq.accept {
|
if !seq.accept {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var listener net.Listener
|
lis, err := net.ListenTCP("tcp", s.Addr)
|
||||||
|
|
||||||
listener, err := net.ListenTCP("tcp", s.Addr)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
listener = lis
|
||||||
|
|
||||||
if s.TLS {
|
if s.TLS {
|
||||||
cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey)
|
cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
certpool := x509.NewCertPool()
|
||||||
|
certpool.AddCert(x509Cert)
|
||||||
|
|
||||||
listener = tls.NewListener(
|
listener = tls.NewListener(
|
||||||
listener,
|
listener,
|
||||||
&tls.Config{
|
&tls.Config{
|
||||||
|
RootCAs: certpool,
|
||||||
Certificates: []tls.Certificate{cert},
|
Certificates: []tls.Certificate{cert},
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "example.com",
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
MaxVersion: tls.VersionTLS12,
|
||||||
|
ClientAuth: tls.VerifyClientCertIfGiven,
|
||||||
|
ClientCAs: certpool,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := listener.Accept()
|
conn, err := listener.Accept()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
listener.Close()
|
_ = conn.Close()
|
||||||
|
})
|
||||||
|
|
||||||
if seq.payloadIn == "" {
|
if seq.payloadIn == "" {
|
||||||
conn.Close()
|
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
|
buf := make([]byte, len(seq.payloadIn))
|
||||||
buf := make([]byte, 1024)
|
n, err := conn.Read(buf)
|
||||||
n, _ := conn.Read(buf)
|
require.NoError(t, err)
|
||||||
|
|
||||||
recv := strings.TrimSpace(string(buf[:n]))
|
recv := strings.TrimSpace(string(buf[:n]))
|
||||||
|
|
||||||
switch recv {
|
switch recv {
|
||||||
case seq.payloadIn:
|
case seq.payloadIn:
|
||||||
_, _ = conn.Write([]byte(seq.payloadOut))
|
if _, err := conn.Write([]byte(seq.payloadOut)); err != nil {
|
||||||
|
t.Errorf("failed to write payload: %v", err)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
_, _ = conn.Write([]byte("FAULT\n"))
|
if _, err := conn.Write([]byte("FAULT\n")); err != nil {
|
||||||
|
t.Errorf("failed to write payload: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defer conn.Close()
|
defer close(s.release)
|
||||||
}
|
|
||||||
|
|
||||||
close(s.release)
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user