This commit is contained in:
Ivan Ka 2025-08-05 05:09:46 -07:00 committed by GitHub
commit 7e8b31c2b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 288 additions and 9 deletions

View File

@ -239,6 +239,55 @@ func TestEndpointTargetsFromServices(t *testing.T) {
selector: map[string]string{"app": "nginx"},
expected: endpoint.Targets{},
},
{
name: "multiple selectors",
services: []*corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{
Name: "fake",
Namespace: "default",
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{"app": "apache", "version": "v1"},
ExternalIPs: []string{"158.123.32.23"},
},
},
},
namespace: "default",
selector: map[string]string{"version": "v1"},
expected: endpoint.Targets{"158.123.32.23"},
},
{
name: "complex selectors",
services: []*corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{
Name: "fake",
Namespace: "default",
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{
"app": "demo",
"env": "prod",
"team": "devops",
"version": "v1",
"release": "stable",
"track": "daily",
"tier": "backend",
},
ExternalIPs: []string{"158.123.32.23"},
},
},
},
namespace: "default",
selector: map[string]string{
"version": "v1",
"release": "stable",
"tier": "backend",
"app": "demo",
},
expected: endpoint.Targets{"158.123.32.23"},
},
}
for _, tt := range tests {

View File

@ -24,8 +24,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
networkingv1alpha3api "istio.io/api/networking/v1beta1"
networkingv1alpha3 "istio.io/client-go/pkg/apis/networking/v1beta1"
istionetworking "istio.io/api/networking/v1beta1"
networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
istiofake "istio.io/client-go/pkg/clientset/versioned/fake"
v1 "k8s.io/api/core/v1"
networkv1 "k8s.io/api/networking/v1"
@ -1477,7 +1477,7 @@ func testGatewayEndpoints(t *testing.T) {
t.Run(ti.title, func(t *testing.T) {
t.Parallel()
fakeKubernetesClient := fake.NewSimpleClientset()
fakeKubernetesClient := fake.NewClientset()
for _, lb := range ti.lbServices {
service := lb.Service()
@ -1522,9 +1522,119 @@ func testGatewayEndpoints(t *testing.T) {
}
}
func TestGatewaySource_GWSelectorMatchServiceSelector(t *testing.T) {
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "fake-service",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app": "demo",
"env": "prod",
"team": "devops",
"version": "v1",
"release": "stable",
"track": "daily",
"tier": "backend",
},
ExternalIPs: []string{"10.10.10.255"},
},
}
tests := []struct {
name string
selectors map[string]string
expected []*endpoint.Endpoint
}{
{
name: "gw single selector match with single service selector",
selectors: map[string]string{
"version": "v1",
},
expected: []*endpoint.Endpoint{
endpoint.NewEndpoint("example.org", endpoint.RecordTypeA, "10.10.10.255").WithLabel("resource", "gateway/default/fake-gateway"),
},
},
{
name: "gw selector match all service selectors",
selectors: map[string]string{
"app": "demo",
"env": "prod",
"team": "devops",
"version": "v1",
"release": "stable",
"track": "daily",
"tier": "backend",
},
expected: []*endpoint.Endpoint{
endpoint.NewEndpoint("example.org", endpoint.RecordTypeA, "10.10.10.255").WithLabel("resource", "gateway/default/fake-gateway"),
},
},
{
name: "gw selector has subset of service selectors",
selectors: map[string]string{
"version": "v1",
"release": "stable",
"tier": "backend",
"app": "demo",
},
expected: []*endpoint.Endpoint{
endpoint.NewEndpoint("example.org", endpoint.RecordTypeA, "10.10.10.255").WithLabel("resource", "gateway/default/fake-gateway"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fakeKubeClient := fake.NewClientset()
fakeIstioClient := istiofake.NewSimpleClientset()
src, err := NewIstioGatewaySource(
t.Context(),
fakeKubeClient,
fakeIstioClient,
"",
"",
"",
false,
false,
)
require.NoError(t, err)
require.NotNil(t, src)
_, err = fakeKubeClient.CoreV1().Services(svc.Namespace).Create(t.Context(), svc, metav1.CreateOptions{})
require.NoError(t, err)
gw := &networkingv1beta1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "fake-gateway",
Namespace: "default",
},
Spec: istionetworking.Gateway{
Servers: []*istionetworking.Server{
{
Hosts: []string{"example.org"},
},
},
Selector: tt.selectors,
},
}
_, err = fakeIstioClient.NetworkingV1beta1().Gateways(gw.Namespace).Create(context.Background(), gw, metav1.CreateOptions{})
require.NoError(t, err)
res, err := src.Endpoints(t.Context())
require.NoError(t, err)
validateEndpoints(t, res, tt.expected)
})
}
}
// gateway specific helper functions
func newTestGatewaySource(loadBalancerList []fakeIngressGatewayService, ingressList []fakeIngress) (*gatewaySource, error) {
fakeKubernetesClient := fake.NewSimpleClientset()
fakeKubernetesClient := fake.NewClientset()
fakeIstioClient := istiofake.NewSimpleClientset()
for _, lb := range loadBalancerList {
@ -1612,22 +1722,22 @@ type fakeGatewayConfig struct {
selector map[string]string
}
func (c fakeGatewayConfig) Config() *networkingv1alpha3.Gateway {
gw := &networkingv1alpha3.Gateway{
func (c fakeGatewayConfig) Config() *networkingv1beta1.Gateway {
gw := &networkingv1beta1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: c.name,
Namespace: c.namespace,
Annotations: c.annotations,
},
Spec: networkingv1alpha3api.Gateway{
Spec: istionetworking.Gateway{
Servers: nil,
Selector: c.selector,
},
}
var servers []*networkingv1alpha3api.Server
var servers []*istionetworking.Server
for _, dnsnames := range c.dnsnames {
servers = append(servers, &networkingv1alpha3api.Server{
servers = append(servers, &istionetworking.Server{
Hosts: dnsnames,
})
}

View File

@ -2212,3 +2212,123 @@ func TestVirtualServiceSourceGetGateway(t *testing.T) {
})
}
}
func TestGatewaySource_GWVServiceSelectorMatchServiceSelector(t *testing.T) {
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "fake-service",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app": "demo",
"env": "prod",
"team": "devops",
"version": "v1",
"release": "stable",
"track": "daily",
"tier": "backend",
},
ExternalIPs: []string{"10.10.10.255"},
},
}
tests := []struct {
name string
selectors map[string]string
expected []*endpoint.Endpoint
}{
{
name: "gw single selector match with single service selector",
selectors: map[string]string{
"version": "v1",
},
expected: []*endpoint.Endpoint{
endpoint.NewEndpoint("example.org", endpoint.RecordTypeA, "10.10.10.255").WithLabel("resource", "gateway/default/fake-gateway"),
},
},
{
name: "gw selector match all service selectors",
selectors: map[string]string{
"app": "demo",
"env": "prod",
"team": "devops",
"version": "v1",
"release": "stable",
"track": "daily",
"tier": "backend",
},
expected: []*endpoint.Endpoint{
endpoint.NewEndpoint("example.org", endpoint.RecordTypeA, "10.10.10.255").WithLabel("resource", "gateway/default/fake-gateway"),
},
},
{
name: "gw selector has subset of service selectors",
selectors: map[string]string{
"version": "v1",
"release": "stable",
"tier": "backend",
"app": "demo",
},
expected: []*endpoint.Endpoint{
endpoint.NewEndpoint("example.org", endpoint.RecordTypeA, "10.10.10.255").WithLabel("resource", "gateway/default/fake-gateway"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fakeKubeClient := fake.NewClientset()
fakeIstioClient := istiofake.NewSimpleClientset()
src, err := NewIstioGatewaySource(
t.Context(),
fakeKubeClient,
fakeIstioClient,
"",
"",
"",
false,
false,
)
require.NoError(t, err)
require.NotNil(t, src)
_, err = fakeKubeClient.CoreV1().Services(svc.Namespace).Create(context.Background(), svc, metav1.CreateOptions{})
require.NoError(t, err)
gw := &networkingv1beta1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "fake-gateway",
Namespace: "default",
},
Spec: istionetworking.Gateway{
Servers: []*istionetworking.Server{
{
Hosts: []string{"example.org"},
},
},
Selector: tt.selectors,
},
}
_, err = fakeIstioClient.NetworkingV1beta1().Gateways(gw.Namespace).Create(context.Background(), gw, metav1.CreateOptions{})
require.NoError(t, err)
gwService := &networkingv1beta1.VirtualService{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
Spec: istionetworking.VirtualService{
Gateways: []string{gw.Namespace + "/" + gw.Name},
Hosts: []string{"example.org"},
ExportTo: []string{"*"},
},
}
_, err = fakeIstioClient.NetworkingV1beta1().VirtualServices(gwService.Namespace).Create(t.Context(), gwService, metav1.CreateOptions{})
require.NoError(t, err)
res, err := src.Endpoints(t.Context())
require.NoError(t, err)
validateEndpoints(t, res, tt.expected)
})
}
}