mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
Merge pull request #107393 from danwinship/filter-endpoints
kube-proxy endpoint filtering unit test refactoring
This commit is contained in:
commit
108e8136e2
@ -17,376 +17,264 @@ limitations under the License.
|
|||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
kerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFilterEndpoints(t *testing.T) {
|
func checkExpectedEndpoints(expected sets.String, actual []Endpoint) error {
|
||||||
type endpoint struct {
|
var errs []error
|
||||||
ip string
|
|
||||||
zoneHints sets.String
|
expectedCopy := sets.NewString(expected.UnsortedList()...)
|
||||||
unready bool
|
for _, ep := range actual {
|
||||||
|
if !expectedCopy.Has(ep.String()) {
|
||||||
|
errs = append(errs, fmt.Errorf("unexpected endpoint %v", ep))
|
||||||
}
|
}
|
||||||
|
expectedCopy.Delete(ep.String())
|
||||||
|
}
|
||||||
|
if len(expectedCopy) > 0 {
|
||||||
|
errs = append(errs, fmt.Errorf("missing endpoints %v", expectedCopy.UnsortedList()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return kerrors.NewAggregate(errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterEndpoints(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
hintsEnabled bool
|
hintsEnabled bool
|
||||||
nodeLabels map[string]string
|
nodeLabels map[string]string
|
||||||
serviceInfo ServicePort
|
serviceInfo ServicePort
|
||||||
endpoints []endpoint
|
endpoints []Endpoint
|
||||||
expectedEndpoints []endpoint
|
expectedEndpoints sets.String
|
||||||
}{{
|
}{{
|
||||||
name: "hints enabled, hints annotation == auto",
|
name: "hints enabled, hints annotation == auto",
|
||||||
hintsEnabled: true,
|
hintsEnabled: true,
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false, hintsAnnotation: "auto"},
|
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false, hintsAnnotation: "auto"},
|
||||||
endpoints: []endpoint{
|
endpoints: []Endpoint{
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.6:80"),
|
||||||
}, {
|
}, {
|
||||||
name: "hints, hints annotation == disabled, hints ignored",
|
name: "hints, hints annotation == disabled, hints ignored",
|
||||||
hintsEnabled: true,
|
hintsEnabled: true,
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false, hintsAnnotation: "disabled"},
|
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false, hintsAnnotation: "disabled"},
|
||||||
endpoints: []endpoint{
|
endpoints: []Endpoint{
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
}, {
|
}, {
|
||||||
name: "hints, hints annotation == aUto (wrong capitalization), hints ignored",
|
name: "hints, hints annotation == aUto (wrong capitalization), hints ignored",
|
||||||
hintsEnabled: true,
|
hintsEnabled: true,
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false, hintsAnnotation: "aUto"},
|
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false, hintsAnnotation: "aUto"},
|
||||||
endpoints: []endpoint{
|
endpoints: []Endpoint{
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
}, {
|
}, {
|
||||||
name: "hints, hints annotation empty, hints ignored",
|
name: "hints, hints annotation empty, hints ignored",
|
||||||
hintsEnabled: true,
|
hintsEnabled: true,
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false},
|
serviceInfo: &BaseServiceInfo{nodeLocalExternal: false},
|
||||||
endpoints: []endpoint{
|
endpoints: []Endpoint{
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
}, {
|
}, {
|
||||||
name: "node local endpoints, hints are ignored",
|
name: "node local endpoints, hints are ignored",
|
||||||
hintsEnabled: true,
|
hintsEnabled: true,
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
serviceInfo: &BaseServiceInfo{nodeLocalExternal: true},
|
serviceInfo: &BaseServiceInfo{nodeLocalExternal: true, hintsAnnotation: "auto"},
|
||||||
endpoints: []endpoint{
|
endpoints: []Endpoint{
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []endpoint{
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
}, {
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
name: "empty node labels",
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
hintsEnabled: true,
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
nodeLabels: map[string]string{},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
},
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80"),
|
||||||
|
}, {
|
||||||
|
name: "empty zone label",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: ""},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80"),
|
||||||
|
}, {
|
||||||
|
name: "node in different zone, no endpoint filtering",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-b"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80"),
|
||||||
|
}, {
|
||||||
|
name: "normal endpoint filtering, auto annotation",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.6:80"),
|
||||||
|
}, {
|
||||||
|
name: "unready endpoint",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: false},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80"),
|
||||||
|
}, {
|
||||||
|
name: "only unready endpoints in same zone (should not filter)",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: false},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: false},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
|
}, {
|
||||||
|
name: "normal endpoint filtering, Auto annotation",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "Auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.6:80"),
|
||||||
|
}, {
|
||||||
|
name: "hintsAnnotation empty, no filtering applied",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: ""},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
|
}, {
|
||||||
|
name: "hintsAnnotation disabled, no filtering applied",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "disabled"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
|
}, {
|
||||||
|
name: "missing hints, no filtering applied",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: nil, Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-a"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.5:80", "10.1.2.6:80"),
|
||||||
|
}, {
|
||||||
|
name: "multiple hints per endpoint, filtering includes any endpoint with zone included",
|
||||||
|
hintsEnabled: true,
|
||||||
|
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-c"},
|
||||||
|
serviceInfo: &BaseServiceInfo{hintsAnnotation: "auto"},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.3:80", ZoneHints: sets.NewString("zone-a", "zone-b", "zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.4:80", ZoneHints: sets.NewString("zone-b", "zone-c"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.5:80", ZoneHints: sets.NewString("zone-b", "zone-d"), Ready: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.1.2.6:80", ZoneHints: sets.NewString("zone-c"), Ready: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.1.2.3:80", "10.1.2.4:80", "10.1.2.6:80"),
|
||||||
|
}, {
|
||||||
|
name: "internalTrafficPolicy: Local, with empty endpoints",
|
||||||
|
serviceInfo: &BaseServiceInfo{nodeLocalInternal: true},
|
||||||
|
endpoints: []Endpoint{},
|
||||||
|
expectedEndpoints: nil,
|
||||||
|
}, {
|
||||||
|
name: "internalTrafficPolicy: Local, but all endpoints are remote",
|
||||||
|
serviceInfo: &BaseServiceInfo{nodeLocalInternal: true},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", Ready: true, IsLocal: false},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.0.0.1:80", Ready: true, IsLocal: false},
|
||||||
|
},
|
||||||
|
expectedEndpoints: nil,
|
||||||
|
}, {
|
||||||
|
name: "internalTrafficPolicy: Local, all endpoints are local",
|
||||||
|
serviceInfo: &BaseServiceInfo{nodeLocalInternal: true},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", Ready: true, IsLocal: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.0.0.1:80", Ready: true, IsLocal: true},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.0.0.0:80", "10.0.0.1:80"),
|
||||||
|
}, {
|
||||||
|
name: "internalTrafficPolicy: Local, some endpoints are local",
|
||||||
|
serviceInfo: &BaseServiceInfo{nodeLocalInternal: true},
|
||||||
|
endpoints: []Endpoint{
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", Ready: true, IsLocal: true},
|
||||||
|
&BaseEndpointInfo{Endpoint: "10.0.0.1:80", Ready: true, IsLocal: false},
|
||||||
|
},
|
||||||
|
expectedEndpoints: sets.NewString("10.0.0.0:80"),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
endpointsToStringArray := func(endpoints []Endpoint) []string {
|
|
||||||
result := make([]string, 0, len(endpoints))
|
|
||||||
for _, ep := range endpoints {
|
|
||||||
result = append(result, ep.String())
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, tc.hintsEnabled)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TopologyAwareHints, tc.hintsEnabled)()
|
||||||
|
|
||||||
endpoints := []Endpoint{}
|
filteredEndpoints := FilterEndpoints(tc.endpoints, tc.serviceInfo, tc.nodeLabels)
|
||||||
for _, ep := range tc.endpoints {
|
err := checkExpectedEndpoints(tc.expectedEndpoints, filteredEndpoints)
|
||||||
endpoints = append(endpoints, &BaseEndpointInfo{Endpoint: ep.ip, ZoneHints: ep.zoneHints, Ready: !ep.unready})
|
if err != nil {
|
||||||
}
|
t.Errorf(err.Error())
|
||||||
|
|
||||||
expectedEndpoints := []Endpoint{}
|
|
||||||
for _, ep := range tc.expectedEndpoints {
|
|
||||||
expectedEndpoints = append(expectedEndpoints, &BaseEndpointInfo{Endpoint: ep.ip, ZoneHints: ep.zoneHints, Ready: !ep.unready})
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredEndpoints := FilterEndpoints(endpoints, tc.serviceInfo, tc.nodeLabels)
|
|
||||||
if len(filteredEndpoints) != len(expectedEndpoints) {
|
|
||||||
t.Errorf("expected %d filtered endpoints, got %d", len(expectedEndpoints), len(filteredEndpoints))
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(filteredEndpoints, expectedEndpoints) {
|
|
||||||
t.Errorf("expected %v, got %v", endpointsToStringArray(expectedEndpoints), endpointsToStringArray(filteredEndpoints))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_filterEndpointsWithHints(t *testing.T) {
|
|
||||||
type endpoint struct {
|
|
||||||
ip string
|
|
||||||
zoneHints sets.String
|
|
||||||
unready bool
|
|
||||||
}
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
nodeLabels map[string]string
|
|
||||||
hintsAnnotation string
|
|
||||||
endpoints []endpoint
|
|
||||||
expectedEndpoints []endpoint
|
|
||||||
}{{
|
|
||||||
name: "empty node labels",
|
|
||||||
nodeLabels: map[string]string{},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")}},
|
|
||||||
expectedEndpoints: []endpoint{{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")}},
|
|
||||||
}, {
|
|
||||||
name: "empty zone label",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: ""},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")}},
|
|
||||||
expectedEndpoints: []endpoint{{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")}},
|
|
||||||
}, {
|
|
||||||
name: "node in different zone, no endpoint filtering",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-b"},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")}},
|
|
||||||
expectedEndpoints: []endpoint{{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")}},
|
|
||||||
}, {
|
|
||||||
name: "normal endpoint filtering, auto annotation",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "unready endpoint",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a"), unready: true},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "only unready endpoints in same zone (should not filter)",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a"), unready: true},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a"), unready: true},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a"), unready: true},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a"), unready: true},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "normal endpoint filtering, Auto annotation",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
hintsAnnotation: "Auto",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "hintsAnnotation empty, no filtering applied",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
hintsAnnotation: "",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "hintsAnnotation disabled, no filtering applied",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
hintsAnnotation: "disabled",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "missing hints, no filtering applied",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-a"},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5"},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b")},
|
|
||||||
{ip: "10.1.2.5"},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-a")},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "multiple hints per endpoint, filtering includes any endpoint with zone included",
|
|
||||||
nodeLabels: map[string]string{v1.LabelTopologyZone: "zone-c"},
|
|
||||||
hintsAnnotation: "auto",
|
|
||||||
endpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a", "zone-b", "zone-c")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b", "zone-c")},
|
|
||||||
{ip: "10.1.2.5", zoneHints: sets.NewString("zone-b", "zone-d")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-c")},
|
|
||||||
},
|
|
||||||
expectedEndpoints: []endpoint{
|
|
||||||
{ip: "10.1.2.3", zoneHints: sets.NewString("zone-a", "zone-b", "zone-c")},
|
|
||||||
{ip: "10.1.2.4", zoneHints: sets.NewString("zone-b", "zone-c")},
|
|
||||||
{ip: "10.1.2.6", zoneHints: sets.NewString("zone-c")},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
|
|
||||||
endpointsToStringArray := func(endpoints []Endpoint) []string {
|
|
||||||
result := make([]string, 0, len(endpoints))
|
|
||||||
for _, ep := range endpoints {
|
|
||||||
result = append(result, ep.String())
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
endpoints := []Endpoint{}
|
|
||||||
for _, ep := range tc.endpoints {
|
|
||||||
endpoints = append(endpoints, &BaseEndpointInfo{Endpoint: ep.ip, ZoneHints: ep.zoneHints, Ready: !ep.unready})
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedEndpoints := []Endpoint{}
|
|
||||||
for _, ep := range tc.expectedEndpoints {
|
|
||||||
expectedEndpoints = append(expectedEndpoints, &BaseEndpointInfo{Endpoint: ep.ip, ZoneHints: ep.zoneHints, Ready: !ep.unready})
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredEndpoints := filterEndpointsWithHints(endpoints, tc.hintsAnnotation, tc.nodeLabels)
|
|
||||||
if len(filteredEndpoints) != len(expectedEndpoints) {
|
|
||||||
t.Errorf("expected %d filtered endpoints, got %d", len(expectedEndpoints), len(filteredEndpoints))
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(filteredEndpoints, expectedEndpoints) {
|
|
||||||
t.Errorf("expected %v, got %v", endpointsToStringArray(expectedEndpoints), endpointsToStringArray(filteredEndpoints))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterLocalEndpoint(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
endpoints []Endpoint
|
|
||||||
expected []Endpoint
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "with empty endpoints",
|
|
||||||
endpoints: []Endpoint{},
|
|
||||||
expected: nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "all endpoints not local",
|
|
||||||
endpoints: []Endpoint{
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", IsLocal: false},
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.1:80", IsLocal: false},
|
|
||||||
},
|
|
||||||
expected: nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "all endpoints are local",
|
|
||||||
endpoints: []Endpoint{
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", IsLocal: true},
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.1:80", IsLocal: true},
|
|
||||||
},
|
|
||||||
expected: []Endpoint{
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", IsLocal: true},
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.1:80", IsLocal: true},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "some endpoints are local",
|
|
||||||
endpoints: []Endpoint{
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", IsLocal: true},
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.1:80", IsLocal: false},
|
|
||||||
},
|
|
||||||
expected: []Endpoint{
|
|
||||||
&BaseEndpointInfo{Endpoint: "10.0.0.0:80", IsLocal: true},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
filteredEndpoint := FilterLocalEndpoint(tc.endpoints)
|
|
||||||
if !reflect.DeepEqual(filteredEndpoint, tc.expected) {
|
|
||||||
t.Errorf("expected %v, got %v", tc.expected, filteredEndpoint)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user