github.com/cilium/cilium@v1.16.2/pkg/ciliumenvoyconfig/envoy_l7lb_backend_syncer_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package ciliumenvoyconfig
     5  
     6  import (
     7  	"net/netip"
     8  	"testing"
     9  
    10  	envoy_config_core "github.com/cilium/proxy/go/envoy/config/core/v3"
    11  	endpointv3 "github.com/cilium/proxy/go/envoy/config/endpoint/v3"
    12  	_ "github.com/cilium/proxy/go/envoy/config/listener/v3"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/cilium/cilium/pkg/clustermesh/types"
    17  	"github.com/cilium/cilium/pkg/loadbalancer"
    18  )
    19  
    20  func Test_filterServiceBackends(t *testing.T) {
    21  	t.Run("filter by port number", func(t *testing.T) {
    22  		svc := &loadbalancer.SVC{
    23  			Frontend: loadbalancer.L3n4AddrID{
    24  				L3n4Addr: loadbalancer.L3n4Addr{
    25  					L4Addr: loadbalancer.L4Addr{
    26  						Port: 8080,
    27  					},
    28  				},
    29  			},
    30  			Backends: []*loadbalancer.Backend{
    31  				{
    32  					FEPortName: "http",
    33  					L3n4Addr: loadbalancer.L3n4Addr{
    34  						L4Addr: loadbalancer.L4Addr{
    35  							Port: 3000,
    36  						},
    37  					},
    38  				},
    39  			},
    40  		}
    41  
    42  		t.Run("all ports are allowed", func(t *testing.T) {
    43  			backends := filterServiceBackends(svc, nil)
    44  			assert.Len(t, backends, 1)
    45  			assert.Len(t, backends["*"], 1)
    46  		})
    47  		t.Run("only http port", func(t *testing.T) {
    48  			backends := filterServiceBackends(svc, []string{"8080"})
    49  			assert.Len(t, backends, 1)
    50  			assert.Len(t, backends["8080"], 1)
    51  		})
    52  		t.Run("named and number ports", func(t *testing.T) {
    53  			backends := filterServiceBackends(svc, []string{"8080", "http"})
    54  			assert.Len(t, backends, 2)
    55  			assert.Len(t, backends["8080"], 1)
    56  			assert.Len(t, backends["http"], 1)
    57  		})
    58  		t.Run("no match", func(t *testing.T) {
    59  			backends := filterServiceBackends(svc, []string{"8000"})
    60  			assert.Len(t, backends, 0)
    61  		})
    62  	})
    63  
    64  	t.Run("filter by port named", func(t *testing.T) {
    65  		svc := &loadbalancer.SVC{
    66  			Frontend: loadbalancer.L3n4AddrID{
    67  				L3n4Addr: loadbalancer.L3n4Addr{
    68  					L4Addr: loadbalancer.L4Addr{
    69  						Port: 8000,
    70  					},
    71  				},
    72  			},
    73  			Backends: []*loadbalancer.Backend{
    74  				{
    75  					FEPortName: "http",
    76  					L3n4Addr: loadbalancer.L3n4Addr{
    77  						L4Addr: loadbalancer.L4Addr{
    78  							Port: 8080,
    79  						},
    80  					},
    81  				},
    82  				{
    83  					FEPortName: "https",
    84  					L3n4Addr: loadbalancer.L3n4Addr{
    85  						L4Addr: loadbalancer.L4Addr{
    86  							Port: 8443,
    87  						},
    88  					},
    89  				},
    90  				{
    91  					FEPortName: "metrics",
    92  					L3n4Addr: loadbalancer.L3n4Addr{
    93  						L4Addr: loadbalancer.L4Addr{
    94  							Port: 8081,
    95  						},
    96  					},
    97  				},
    98  			},
    99  		}
   100  
   101  		t.Run("all ports are allowed", func(t *testing.T) {
   102  			backends := filterServiceBackends(svc, nil)
   103  			assert.Len(t, backends, 1)
   104  			assert.Len(t, backends["*"], 3)
   105  		})
   106  		t.Run("only http named port", func(t *testing.T) {
   107  			backends := filterServiceBackends(svc, []string{"http"})
   108  			assert.Len(t, backends, 1)
   109  			assert.Len(t, backends["http"], 1)
   110  		})
   111  		t.Run("multiple named ports", func(t *testing.T) {
   112  			backends := filterServiceBackends(svc, []string{"http", "metrics"})
   113  			assert.Len(t, backends, 2)
   114  
   115  			assert.Len(t, backends["http"], 1)
   116  			assert.Equal(t, (int)(backends["http"][0].Port), 8080)
   117  
   118  			assert.Len(t, backends["metrics"], 1)
   119  			assert.Equal(t, (int)(backends["metrics"][0].Port), 8081)
   120  		})
   121  	})
   122  
   123  	t.Run("filter with preferred backend", func(t *testing.T) {
   124  		svc := &loadbalancer.SVC{
   125  			Frontend: loadbalancer.L3n4AddrID{
   126  				L3n4Addr: loadbalancer.L3n4Addr{
   127  					L4Addr: loadbalancer.L4Addr{
   128  						Port: 8000,
   129  					},
   130  				},
   131  			},
   132  			Backends: []*loadbalancer.Backend{
   133  				{
   134  					FEPortName: "http",
   135  					L3n4Addr: loadbalancer.L3n4Addr{
   136  						L4Addr: loadbalancer.L4Addr{
   137  							Port: 8080,
   138  						},
   139  					},
   140  					Preferred: loadbalancer.Preferred(true),
   141  				},
   142  				{
   143  					FEPortName: "http",
   144  					L3n4Addr: loadbalancer.L3n4Addr{
   145  						L4Addr: loadbalancer.L4Addr{
   146  							Port: 8081,
   147  						},
   148  					},
   149  				},
   150  				{
   151  					FEPortName: "https",
   152  					L3n4Addr: loadbalancer.L3n4Addr{
   153  						L4Addr: loadbalancer.L4Addr{
   154  							Port: 443,
   155  						},
   156  					},
   157  				},
   158  				{
   159  					FEPortName: "80",
   160  					L3n4Addr: loadbalancer.L3n4Addr{
   161  						L4Addr: loadbalancer.L4Addr{
   162  							Port: 8080,
   163  						},
   164  					},
   165  					Preferred: loadbalancer.Preferred(true),
   166  				},
   167  				{
   168  					FEPortName: "80",
   169  					L3n4Addr: loadbalancer.L3n4Addr{
   170  						L4Addr: loadbalancer.L4Addr{
   171  							Port: 8081,
   172  						},
   173  					},
   174  				},
   175  			},
   176  		}
   177  
   178  		t.Run("all ports are allowed", func(t *testing.T) {
   179  			backends := filterServiceBackends(svc, nil)
   180  			assert.Len(t, backends, 1)
   181  			assert.Len(t, backends["*"], 2)
   182  		})
   183  
   184  		t.Run("only named ports", func(t *testing.T) {
   185  			backends := filterServiceBackends(svc, []string{"http"})
   186  			assert.Len(t, backends, 1)
   187  			assert.Len(t, backends["http"], 1)
   188  		})
   189  		t.Run("multiple named ports", func(t *testing.T) {
   190  			backends := filterServiceBackends(svc, []string{"http", "https"})
   191  			assert.Len(t, backends, 1)
   192  
   193  			assert.Len(t, backends["http"], 1)
   194  			assert.Equal(t, (int)(backends["http"][0].Port), 8080)
   195  		})
   196  
   197  		t.Run("only port number", func(t *testing.T) {
   198  			backends := filterServiceBackends(svc, []string{"80"})
   199  			assert.Len(t, backends, 1)
   200  
   201  			assert.Len(t, backends["80"], 1)
   202  			assert.Equal(t, (int)(backends["80"][0].Port), 8080)
   203  		})
   204  	})
   205  }
   206  
   207  func TestGetEndpointsForLBBackends(t *testing.T) {
   208  	testAddr, err := netip.ParseAddr("192.128.1.1")
   209  	require.NoError(t, err)
   210  
   211  	serviceName := loadbalancer.ServiceName{
   212  		Namespace: "test-ns",
   213  		Name:      "test-name",
   214  		Cluster:   "test-cluster",
   215  	}
   216  	backends := map[string][]*loadbalancer.Backend{
   217  		"12000": {
   218  			{
   219  				L3n4Addr: *loadbalancer.NewL3n4Addr(loadbalancer.TCP, types.AddrClusterFrom(testAddr, 0), 12000, 3),
   220  			},
   221  		},
   222  		"13000": {
   223  			{
   224  				L3n4Addr: *loadbalancer.NewL3n4Addr(loadbalancer.TCP, types.AddrClusterFrom(testAddr, 0), 13000, 3),
   225  			},
   226  		},
   227  		"*": {
   228  			{
   229  				L3n4Addr: *loadbalancer.NewL3n4Addr(loadbalancer.TCP, types.AddrClusterFrom(testAddr, 0), 15000, 3),
   230  			},
   231  		},
   232  	}
   233  
   234  	endpoints := getEndpointsForLBBackends(serviceName, backends)
   235  	assert.Len(t, endpoints, 4)
   236  
   237  	var allClusterNames []string
   238  	for _, ep := range endpoints {
   239  		allClusterNames = append(allClusterNames, ep.GetClusterName())
   240  
   241  		assert.Len(t, ep.GetEndpoints(), 1)
   242  		assert.Len(t, ep.GetEndpoints()[0].GetLbEndpoints(), 1)
   243  		assert.Equal(t, ep.GetEndpoints()[0].GetLbEndpoints()[0].GetHostIdentifier().(*endpointv3.LbEndpoint_Endpoint).Endpoint.Address.GetAddress().(*envoy_config_core.Address_SocketAddress).SocketAddress.Address, "192.128.1.1")
   244  	}
   245  
   246  	assert.Contains(t, allClusterNames, "test-cluster/test-ns/test-name:12000")
   247  	assert.Contains(t, allClusterNames, "test-cluster/test-ns/test-name:13000")
   248  	assert.Contains(t, allClusterNames, "test-cluster/test-ns/test-name:*")
   249  	assert.Contains(t, allClusterNames, "test-cluster/test-ns/test-name")
   250  }