From 90175571698d7cb0e4184d257a425f0bd11c713d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sim=C3=A3o=20Gomes=20Viana?= Date: Thu, 29 Apr 2021 18:52:22 +0200 Subject: reverseproxy: fix hash selection policy (#4137) * caddyhttp: reverseproxy: fix hash selection policy Fixes: #4135 Test: go test './...' -count=1 * caddyhttp: reverseproxy: add test to catch #4135 If you revert the last commit, the test will fail. --- .../caddyhttp/reverseproxy/selectionpolicies.go | 3 +-- .../reverseproxy/selectionpolicies_test.go | 29 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/modules/caddyhttp/reverseproxy/selectionpolicies.go b/modules/caddyhttp/reverseproxy/selectionpolicies.go index 357ee33..001f7f8 100644 --- a/modules/caddyhttp/reverseproxy/selectionpolicies.go +++ b/modules/caddyhttp/reverseproxy/selectionpolicies.go @@ -523,8 +523,7 @@ func hostByHashing(pool []*Upstream, s string) *Upstream { } index := hash(s) % poolLen for i := uint32(0); i < poolLen; i++ { - index += i - upstream := pool[index%poolLen] + upstream := pool[(index+i)%poolLen] if upstream.Available() { return upstream } diff --git a/modules/caddyhttp/reverseproxy/selectionpolicies_test.go b/modules/caddyhttp/reverseproxy/selectionpolicies_test.go index 70d05ac..60a2702 100644 --- a/modules/caddyhttp/reverseproxy/selectionpolicies_test.go +++ b/modules/caddyhttp/reverseproxy/selectionpolicies_test.go @@ -198,6 +198,35 @@ func TestIPHashPolicy(t *testing.T) { if h != nil { t.Error("Expected ip hash policy host to be nil.") } + + // Reproduce #4135 + pool = UpstreamPool{ + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + {Host: new(upstreamHost)}, + } + pool[0].SetHealthy(false) + pool[1].SetHealthy(false) + pool[2].SetHealthy(false) + pool[3].SetHealthy(false) + pool[4].SetHealthy(false) + pool[5].SetHealthy(false) + pool[6].SetHealthy(false) + pool[7].SetHealthy(false) + pool[8].SetHealthy(true) + + // We should get a result back when there is one healthy host left. + h = ipHash.Select(pool, req, nil) + if h == nil { + // If it is nil, it means we missed a host even though one is available + t.Error("Expected ip hash policy host to not be nil, but it is nil.") + } } func TestFirstPolicy(t *testing.T) { -- cgit v1.2.3