istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/sidecar_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package model
    16  
    17  import (
    18  	"encoding/json"
    19  	"reflect"
    20  	"strconv"
    21  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/google/go-cmp/cmp/cmpopts"
    27  	"google.golang.org/protobuf/types/known/durationpb"
    28  	"google.golang.org/protobuf/types/known/wrapperspb"
    29  	"k8s.io/apimachinery/pkg/types"
    30  
    31  	"istio.io/api/mesh/v1alpha1"
    32  	networking "istio.io/api/networking/v1alpha3"
    33  	"istio.io/api/type/v1beta1"
    34  	"istio.io/istio/pilot/pkg/features"
    35  	"istio.io/istio/pilot/pkg/serviceregistry/provider"
    36  	"istio.io/istio/pkg/config"
    37  	"istio.io/istio/pkg/config/constants"
    38  	"istio.io/istio/pkg/config/host"
    39  	"istio.io/istio/pkg/config/mesh"
    40  	"istio.io/istio/pkg/config/schema/gvk"
    41  	"istio.io/istio/pkg/config/schema/kind"
    42  	"istio.io/istio/pkg/config/visibility"
    43  	"istio.io/istio/pkg/test"
    44  	"istio.io/istio/pkg/test/util/assert"
    45  	"istio.io/istio/pkg/util/sets"
    46  )
    47  
    48  var (
    49  	port9999 = []*Port{
    50  		{
    51  			Name:     "uds",
    52  			Port:     9999,
    53  			Protocol: "HTTP",
    54  		},
    55  	}
    56  
    57  	port7000 = []*Port{
    58  		{
    59  			Name:     "uds",
    60  			Port:     7000,
    61  			Protocol: "HTTP",
    62  		},
    63  	}
    64  
    65  	port7443 = []*Port{
    66  		{
    67  			Port:     7443,
    68  			Protocol: "GRPC",
    69  			Name:     "service-grpc-tls",
    70  		},
    71  	}
    72  
    73  	port7442 = []*Port{
    74  		{
    75  			Port:     7442,
    76  			Protocol: "HTTP",
    77  			Name:     "http-tls",
    78  		},
    79  	}
    80  
    81  	port744x = []*Port{
    82  		{
    83  			Port:     7443,
    84  			Protocol: "GRPC",
    85  			Name:     "service-grpc-tls",
    86  		},
    87  		{
    88  			Port:     7442,
    89  			Protocol: "HTTP",
    90  			Name:     "http-tls",
    91  		},
    92  	}
    93  
    94  	port803x = []*Port{
    95  		{
    96  			Port:     8031,
    97  			Protocol: "TCP",
    98  			Name:     "tcp-1",
    99  		},
   100  		{
   101  			Port:     8032,
   102  			Protocol: "TCP",
   103  			Name:     "tcp-2",
   104  		},
   105  		{
   106  			Port:     8033,
   107  			Protocol: "TCP",
   108  			Name:     "tcp-3",
   109  		},
   110  		{
   111  			Port:     8034,
   112  			Protocol: "TCP",
   113  			Name:     "tcp-4",
   114  		},
   115  		{
   116  			Port:     8035,
   117  			Protocol: "TCP",
   118  			Name:     "tcp-5",
   119  		},
   120  	}
   121  
   122  	twoMatchingPorts = []*Port{
   123  		{
   124  			Port:     7443,
   125  			Protocol: "GRPC",
   126  			Name:     "service-grpc-tls",
   127  		},
   128  		{
   129  			Port:     7442,
   130  			Protocol: "HTTP",
   131  			Name:     "http-tls",
   132  		},
   133  	}
   134  
   135  	port8000 = []*Port{
   136  		{
   137  			Name:     "uds",
   138  			Port:     8000,
   139  			Protocol: "HTTP",
   140  		},
   141  	}
   142  
   143  	port9000 = []*Port{
   144  		{
   145  			Name: "port1",
   146  			Port: 9000,
   147  		},
   148  	}
   149  
   150  	twoPorts = []*Port{
   151  		{
   152  			Name:     "uds",
   153  			Port:     8000,
   154  			Protocol: "HTTP",
   155  		},
   156  		{
   157  			Name:     "uds",
   158  			Port:     7000,
   159  			Protocol: "HTTP",
   160  		},
   161  	}
   162  
   163  	allPorts = []*Port{
   164  		{
   165  			Name:     "uds",
   166  			Port:     8000,
   167  			Protocol: "HTTP",
   168  		},
   169  		{
   170  			Name:     "uds",
   171  			Port:     7000,
   172  			Protocol: "HTTP",
   173  		},
   174  		{
   175  			Name: "port1",
   176  			Port: 9000,
   177  		},
   178  	}
   179  
   180  	configs1 = &config.Config{
   181  		Meta: config.Meta{
   182  			Name:      "foo",
   183  			Namespace: "not-default",
   184  		},
   185  		Spec: &networking.Sidecar{
   186  			Egress: []*networking.IstioEgressListener{
   187  				{
   188  					Port: &networking.SidecarPort{
   189  						Number:   9000,
   190  						Protocol: "HTTP",
   191  						Name:     "uds",
   192  					},
   193  					Bind:  "1.1.1.1",
   194  					Hosts: []string{"*/*"},
   195  				},
   196  				{
   197  					Hosts: []string{"*/*"},
   198  				},
   199  			},
   200  		},
   201  	}
   202  	configs2 = &config.Config{
   203  		Meta: config.Meta{
   204  			Name:      "foo",
   205  			Namespace: "not-default",
   206  		},
   207  		Spec: &networking.Sidecar{},
   208  	}
   209  
   210  	configs3 = &config.Config{
   211  		Meta: config.Meta{
   212  			Name:      "foo",
   213  			Namespace: "not-default",
   214  		},
   215  		Spec: &networking.Sidecar{
   216  			Egress: []*networking.IstioEgressListener{
   217  				{
   218  					Hosts: []string{"foo/bar", "*/*"},
   219  				},
   220  			},
   221  		},
   222  	}
   223  
   224  	configs4 = &config.Config{
   225  		Meta: config.Meta{
   226  			Name:      "foo",
   227  			Namespace: "not-default",
   228  		},
   229  		Spec: &networking.Sidecar{
   230  			Egress: []*networking.IstioEgressListener{
   231  				{
   232  					Port: &networking.SidecarPort{
   233  						Number:   8000,
   234  						Protocol: "HTTP",
   235  						Name:     "uds",
   236  					},
   237  					Hosts: []string{"foo/*"},
   238  				},
   239  			},
   240  		},
   241  	}
   242  
   243  	configs5 = &config.Config{
   244  		Meta: config.Meta{
   245  			Name:      "foo",
   246  			Namespace: "not-default",
   247  		},
   248  		Spec: &networking.Sidecar{
   249  			Egress: []*networking.IstioEgressListener{
   250  				{
   251  					Port: &networking.SidecarPort{
   252  						Number:   8000,
   253  						Protocol: "HTTP",
   254  						Name:     "uds",
   255  					},
   256  					Hosts: []string{"foo/*"},
   257  				},
   258  			},
   259  		},
   260  	}
   261  
   262  	configs6 = &config.Config{
   263  		Meta: config.Meta{
   264  			Name:      "foo",
   265  			Namespace: "not-default",
   266  		},
   267  		Spec: &networking.Sidecar{
   268  			Egress: []*networking.IstioEgressListener{
   269  				{
   270  					Port: &networking.SidecarPort{
   271  						Number:   8000,
   272  						Protocol: "HTTP",
   273  						Name:     "uds",
   274  					},
   275  					Hosts: []string{"foo/*"},
   276  				},
   277  				{
   278  					Port: &networking.SidecarPort{
   279  						Number:   7000,
   280  						Protocol: "HTTP",
   281  						Name:     "uds",
   282  					},
   283  					Hosts: []string{"foo/*"},
   284  				},
   285  			},
   286  		},
   287  	}
   288  
   289  	configs7 = &config.Config{
   290  		Meta: config.Meta{
   291  			Name: "sidecar-scope-ns1-ns2",
   292  		},
   293  		Spec: &networking.Sidecar{
   294  			Egress: []*networking.IstioEgressListener{
   295  				{
   296  					Port: &networking.SidecarPort{
   297  						Number:   23145,
   298  						Protocol: "TCP",
   299  						Name:     "outbound-tcp",
   300  					},
   301  					Bind: "7.7.7.7",
   302  					Hosts: []string{
   303  						"*/bookinginfo.com",
   304  						"*/private.com",
   305  					},
   306  				},
   307  				{
   308  					Hosts: []string{
   309  						"ns1/*",
   310  						"*/*.tcp.com",
   311  					},
   312  				},
   313  			},
   314  		},
   315  	}
   316  
   317  	configs8 = &config.Config{
   318  		Meta: config.Meta{
   319  			Name: "different-port-name",
   320  		},
   321  		Spec: &networking.Sidecar{
   322  			Egress: []*networking.IstioEgressListener{
   323  				{
   324  					Port: &networking.SidecarPort{
   325  						Number:   7443,
   326  						Protocol: "GRPC",
   327  						Name:     "listener-grpc-tls",
   328  					},
   329  					Hosts: []string{"mesh/*"},
   330  				},
   331  			},
   332  		},
   333  	}
   334  
   335  	configs9 = &config.Config{
   336  		Meta: config.Meta{
   337  			Name: "sidecar-scope-wildcards",
   338  		},
   339  		Spec: &networking.Sidecar{
   340  			Egress: []*networking.IstioEgressListener{
   341  				{
   342  					Port: &networking.SidecarPort{
   343  						Number:   7443,
   344  						Protocol: "GRPC",
   345  						Name:     "grpc-tls",
   346  					},
   347  					Hosts: []string{"*/*"},
   348  				},
   349  				{
   350  					Port: &networking.SidecarPort{
   351  						Number:   7442,
   352  						Protocol: "HTTP",
   353  						Name:     "http-tls",
   354  					},
   355  					Hosts: []string{"ns2/*"},
   356  				},
   357  			},
   358  		},
   359  	}
   360  
   361  	configs10 = &config.Config{
   362  		Meta: config.Meta{
   363  			Name: "sidecar-scope-with-http-proxy",
   364  		},
   365  		Spec: &networking.Sidecar{
   366  			Egress: []*networking.IstioEgressListener{
   367  				{
   368  					Port: &networking.SidecarPort{
   369  						Number:   7443,
   370  						Protocol: "http_proxy",
   371  						Name:     "grpc-tls",
   372  					},
   373  					Hosts: []string{"*/*"},
   374  				},
   375  			},
   376  		},
   377  	}
   378  
   379  	configs11 = &config.Config{
   380  		Meta: config.Meta{
   381  			Name: "sidecar-scope-with-http-proxy-match-virtual-service",
   382  		},
   383  		Spec: &networking.Sidecar{
   384  			Egress: []*networking.IstioEgressListener{
   385  				{
   386  					Port: &networking.SidecarPort{
   387  						Number:   7443,
   388  						Protocol: "http_proxy",
   389  						Name:     "grpc-tls",
   390  					},
   391  					Hosts: []string{"foo/virtualbar"},
   392  				},
   393  			},
   394  		},
   395  	}
   396  
   397  	configs12 = &config.Config{
   398  		Meta: config.Meta{
   399  			Name: "sidecar-scope-with-http-proxy-match-virtual-service-and-service",
   400  		},
   401  		Spec: &networking.Sidecar{
   402  			Egress: []*networking.IstioEgressListener{
   403  				{
   404  					Port: &networking.SidecarPort{
   405  						Number:   7443,
   406  						Protocol: "http_proxy",
   407  						Name:     "grpc-tls",
   408  					},
   409  					Hosts: []string{"foo/virtualbar", "ns2/foo.svc.cluster.local"},
   410  				},
   411  			},
   412  		},
   413  	}
   414  
   415  	configs13 = &config.Config{
   416  		Meta: config.Meta{
   417  			Name: "sidecar-scope-with-illegal-host",
   418  		},
   419  		Spec: &networking.Sidecar{
   420  			Egress: []*networking.IstioEgressListener{
   421  				{
   422  					Port: &networking.SidecarPort{
   423  						Number:   7443,
   424  						Protocol: "http_proxy",
   425  						Name:     "grpc-tls",
   426  					},
   427  					Hosts: []string{"foo", "foo/bar"},
   428  				},
   429  			},
   430  		},
   431  	}
   432  
   433  	configs14 = &config.Config{
   434  		Meta: config.Meta{
   435  			Name: "sidecar-scope-wildcards",
   436  		},
   437  		Spec: &networking.Sidecar{
   438  			Egress: []*networking.IstioEgressListener{
   439  				{
   440  					Port: &networking.SidecarPort{
   441  						Number:   7443,
   442  						Protocol: "GRPC",
   443  						Name:     "grpc-tls",
   444  					},
   445  					Hosts: []string{"*/*"},
   446  				},
   447  				{
   448  					Port: &networking.SidecarPort{
   449  						Number:   7442,
   450  						Protocol: "HTTP",
   451  						Name:     "http-tls",
   452  					},
   453  					Hosts: []string{"ns2/*"},
   454  				},
   455  				{
   456  					Hosts: []string{"*/*"},
   457  				},
   458  			},
   459  		},
   460  	}
   461  
   462  	configs15 = &config.Config{
   463  		Meta: config.Meta{
   464  			Name: "sidecar-scope-with-virtual-service",
   465  		},
   466  		Spec: &networking.Sidecar{
   467  			Egress: []*networking.IstioEgressListener{
   468  				{
   469  					Port: &networking.SidecarPort{
   470  						Number:   7443,
   471  						Protocol: "http",
   472  						Name:     "grpc-tls",
   473  					},
   474  					Hosts: []string{"*/*"},
   475  				},
   476  			},
   477  		},
   478  	}
   479  
   480  	configs16 = &config.Config{
   481  		Meta: config.Meta{
   482  			Name:      "sidecar-scope-with-specific-host",
   483  			Namespace: "ns1",
   484  		},
   485  		Spec: &networking.Sidecar{
   486  			Egress: []*networking.IstioEgressListener{
   487  				{
   488  					Hosts: []string{"*/en.wikipedia.org"},
   489  				},
   490  			},
   491  		},
   492  	}
   493  
   494  	configs17 = &config.Config{
   495  		Meta: config.Meta{
   496  			Name:      "sidecar-scope-with-wildcard-host",
   497  			Namespace: "ns1",
   498  		},
   499  		Spec: &networking.Sidecar{
   500  			Egress: []*networking.IstioEgressListener{
   501  				{
   502  					Hosts: []string{"*/*.wikipedia.org"},
   503  				},
   504  			},
   505  		},
   506  	}
   507  
   508  	configs18 = &config.Config{
   509  		Meta: config.Meta{
   510  			Name:      "sidecar-scope-with-workloadselector-specific-dr-match",
   511  			Namespace: "mynamespace",
   512  			Labels:    map[string]string{"app": "app2"},
   513  		},
   514  		Spec: &networking.Sidecar{},
   515  	}
   516  
   517  	configs19 = &config.Config{
   518  		Meta: config.Meta{
   519  			Name:      "sidecar-scope-with-workloadselector-specific-dr-no-match",
   520  			Namespace: "mynamespace",
   521  			Labels:    map[string]string{"app": "app5"},
   522  		},
   523  		Spec: &networking.Sidecar{},
   524  	}
   525  
   526  	configs20 = &config.Config{
   527  		Meta: config.Meta{
   528  			Name:      "sidecar-scope-with-same-workloadselector-label-drs-merged",
   529  			Namespace: "mynamespace",
   530  			Labels:    map[string]string{"app": "app1"},
   531  		},
   532  		Spec: &networking.Sidecar{},
   533  	}
   534  
   535  	configs21 = &config.Config{
   536  		Meta: config.Meta{
   537  			Name: "virtual-service-destinations-matching-http-virtual-service-ports",
   538  		},
   539  		Spec: &networking.Sidecar{
   540  			Egress: []*networking.IstioEgressListener{
   541  				{
   542  					Hosts: []string{"foo/virtualbar"},
   543  				},
   544  			},
   545  		},
   546  	}
   547  
   548  	configs22 = &config.Config{
   549  		Meta: config.Meta{
   550  			Name: "sidecar-scope-with-multiple-ports",
   551  		},
   552  		Spec: &networking.Sidecar{
   553  			Egress: []*networking.IstioEgressListener{
   554  				{
   555  					Port: &networking.SidecarPort{
   556  						Number:   8031,
   557  						Protocol: "TCP",
   558  						Name:     "tcp-ipc1",
   559  					},
   560  					Hosts: []string{"*/foobar.svc.cluster.local"},
   561  				},
   562  				{
   563  					Port: &networking.SidecarPort{
   564  						Number:   8032,
   565  						Protocol: "TCP",
   566  						Name:     "tcp-ipc2",
   567  					},
   568  					Hosts: []string{"*/foobar.svc.cluster.local"},
   569  				},
   570  				{
   571  					Port: &networking.SidecarPort{
   572  						Number:   8033,
   573  						Protocol: "TCP",
   574  						Name:     "tcp-ipc3",
   575  					},
   576  					Hosts: []string{"*/foobar.svc.cluster.local"},
   577  				},
   578  				{
   579  					Port: &networking.SidecarPort{
   580  						Number:   8034,
   581  						Protocol: "TCP",
   582  						Name:     "tcp-ipc4",
   583  					},
   584  					Hosts: []string{"*/foobar.svc.cluster.local"},
   585  				},
   586  				{
   587  					Port: &networking.SidecarPort{
   588  						Number:   8035,
   589  						Protocol: "TCP",
   590  						Name:     "tcp-ipc5",
   591  					},
   592  					Hosts: []string{"*/foobar.svc.cluster.local"},
   593  				},
   594  			},
   595  		},
   596  	}
   597  
   598  	configs23 = &config.Config{
   599  		Meta: config.Meta{
   600  			Name: "sidecar-scope-with-multiple-ports",
   601  		},
   602  		Spec: &networking.Sidecar{
   603  			Egress: []*networking.IstioEgressListener{
   604  				{
   605  					Port: &networking.SidecarPort{
   606  						Number:   8031,
   607  						Protocol: "TCP",
   608  						Name:     "tcp-ipc1",
   609  					},
   610  					Hosts: []string{"ns1/foobar.svc.cluster.local"},
   611  				},
   612  				{
   613  					Port: &networking.SidecarPort{
   614  						Number:   8032,
   615  						Protocol: "TCP",
   616  						Name:     "tcp-ipc2",
   617  					},
   618  					Hosts: []string{"ns1/foobar.svc.cluster.local"},
   619  				},
   620  				{
   621  					Port: &networking.SidecarPort{
   622  						Number:   8033,
   623  						Protocol: "TCP",
   624  						Name:     "tcp-ipc3",
   625  					},
   626  					Hosts: []string{"ns1/foobar.svc.cluster.local"},
   627  				},
   628  				{
   629  					Port: &networking.SidecarPort{
   630  						Number:   8034,
   631  						Protocol: "TCP",
   632  						Name:     "tcp-ipc4",
   633  					},
   634  					Hosts: []string{"ns1/foobar.svc.cluster.local"},
   635  				},
   636  				{
   637  					Port: &networking.SidecarPort{
   638  						Number:   8035,
   639  						Protocol: "TCP",
   640  						Name:     "tcp-ipc5",
   641  					},
   642  					Hosts: []string{"ns1/foobar.svc.cluster.local"},
   643  				},
   644  			},
   645  		},
   646  	}
   647  
   648  	services1 = []*Service{
   649  		{
   650  			Hostname: "bar",
   651  		},
   652  	}
   653  
   654  	services2 = []*Service{
   655  		{
   656  			Hostname: "bar",
   657  			Ports:    port8000,
   658  		},
   659  		{
   660  			Hostname: "barprime",
   661  		},
   662  	}
   663  
   664  	services3 = []*Service{
   665  		{
   666  			Hostname: "bar",
   667  			Ports:    port9000,
   668  		},
   669  		{
   670  			Hostname: "barprime",
   671  		},
   672  	}
   673  
   674  	services4 = []*Service{
   675  		{
   676  			Hostname: "bar",
   677  		},
   678  		{
   679  			Hostname: "barprime",
   680  		},
   681  	}
   682  
   683  	services5 = []*Service{
   684  		{
   685  			Hostname: "bar",
   686  			Ports:    port8000,
   687  			Attributes: ServiceAttributes{
   688  				Name:      "bar",
   689  				Namespace: "foo",
   690  			},
   691  		},
   692  		{
   693  			Hostname: "barprime",
   694  			Attributes: ServiceAttributes{
   695  				Name:      "barprime",
   696  				Namespace: "foo",
   697  			},
   698  		},
   699  	}
   700  
   701  	services6 = []*Service{
   702  		{
   703  			Hostname: "bar",
   704  			Ports:    twoPorts,
   705  			Attributes: ServiceAttributes{
   706  				Name:      "bar",
   707  				Namespace: "foo",
   708  			},
   709  		},
   710  	}
   711  
   712  	services7 = []*Service{
   713  		{
   714  			Hostname: "bar",
   715  			Ports:    twoPorts,
   716  			Attributes: ServiceAttributes{
   717  				Name:      "bar",
   718  				Namespace: "foo",
   719  			},
   720  		},
   721  		{
   722  			Hostname: "barprime",
   723  			Ports:    port8000,
   724  			Attributes: ServiceAttributes{
   725  				Name:      "barprime",
   726  				Namespace: "foo",
   727  			},
   728  		},
   729  		{
   730  			Hostname: "foo",
   731  			Ports:    allPorts,
   732  			Attributes: ServiceAttributes{
   733  				Name:      "foo",
   734  				Namespace: "foo",
   735  			},
   736  		},
   737  	}
   738  
   739  	services8 = []*Service{
   740  		{
   741  			Hostname: "bookinginfo.com",
   742  			Ports:    port9999,
   743  			Attributes: ServiceAttributes{
   744  				Name:      "bookinginfo.com",
   745  				Namespace: "ns1",
   746  			},
   747  		},
   748  		{
   749  			Hostname: "private.com",
   750  			Attributes: ServiceAttributes{
   751  				Name:      "private.com",
   752  				Namespace: "ns1",
   753  			},
   754  		},
   755  	}
   756  
   757  	services9 = []*Service{
   758  		{
   759  			Hostname: "foo.svc.cluster.local",
   760  			Ports:    port7443,
   761  			Attributes: ServiceAttributes{
   762  				Name:      "foo",
   763  				Namespace: "mesh",
   764  			},
   765  		},
   766  	}
   767  
   768  	services10 = []*Service{
   769  		{
   770  			Hostname: "foo.svc.cluster.local",
   771  			Ports:    port7443,
   772  			Attributes: ServiceAttributes{
   773  				Name:      "foo",
   774  				Namespace: "ns1",
   775  			},
   776  		},
   777  		{
   778  			Hostname: "baz.svc.cluster.local",
   779  			Ports:    port7443,
   780  			Attributes: ServiceAttributes{
   781  				Name:      "baz",
   782  				Namespace: "ns3",
   783  			},
   784  		},
   785  		{
   786  			Hostname: "bar.svc.cluster.local",
   787  			Ports:    port7442,
   788  			Attributes: ServiceAttributes{
   789  				Name:      "bar",
   790  				Namespace: "ns2",
   791  			},
   792  		},
   793  		{
   794  			Hostname: "barprime.svc.cluster.local",
   795  			Ports:    port7442,
   796  			Attributes: ServiceAttributes{
   797  				Name:      "barprime",
   798  				Namespace: "ns3",
   799  			},
   800  		},
   801  	}
   802  
   803  	services11 = []*Service{
   804  		{
   805  			Hostname: "foo.svc.cluster.local",
   806  			Ports:    port7443,
   807  			Attributes: ServiceAttributes{
   808  				Name:      "foo",
   809  				Namespace: "ns1",
   810  			},
   811  		},
   812  		{
   813  			Hostname: "baz.svc.cluster.local",
   814  			Ports:    port7443,
   815  			Attributes: ServiceAttributes{
   816  				Name:      "baz",
   817  				Namespace: "ns3",
   818  			},
   819  		},
   820  		{
   821  			Hostname: "bar.svc.cluster.local",
   822  			Ports:    twoMatchingPorts,
   823  			Attributes: ServiceAttributes{
   824  				Name:      "bar",
   825  				Namespace: "ns2",
   826  			},
   827  		},
   828  		{
   829  			Hostname: "barprime.svc.cluster.local",
   830  			Ports:    port7442,
   831  			Attributes: ServiceAttributes{
   832  				Name:      "barprime",
   833  				Namespace: "ns3",
   834  			},
   835  		},
   836  	}
   837  
   838  	services12 = []*Service{
   839  		{
   840  			Hostname: "foo.svc.cluster.local",
   841  			Ports:    port7443,
   842  			Attributes: ServiceAttributes{
   843  				Name:      "foo",
   844  				Namespace: "ns1",
   845  			},
   846  		},
   847  		{
   848  			Hostname: "foo.svc.cluster.local",
   849  			Ports:    port8000,
   850  			Attributes: ServiceAttributes{
   851  				Name:      "foo",
   852  				Namespace: "ns2",
   853  			},
   854  		},
   855  		{
   856  			Hostname: "baz.svc.cluster.local",
   857  			Ports:    port7443,
   858  			Attributes: ServiceAttributes{
   859  				Name:      "baz",
   860  				Namespace: "ns3",
   861  			},
   862  		},
   863  	}
   864  
   865  	services13 = []*Service{
   866  		{
   867  			Hostname: "foo.svc.cluster.local",
   868  			Ports:    port7443,
   869  			Attributes: ServiceAttributes{
   870  				Name:      "foo",
   871  				Namespace: "ns1",
   872  			},
   873  		},
   874  		{
   875  			Hostname: "foo.svc.cluster.local",
   876  			Ports:    port8000,
   877  			Attributes: ServiceAttributes{
   878  				Name:      "foo",
   879  				Namespace: "mynamespace",
   880  			},
   881  		},
   882  		{
   883  			Hostname: "baz.svc.cluster.local",
   884  			Ports:    port7443,
   885  			Attributes: ServiceAttributes{
   886  				Name:      "baz",
   887  				Namespace: "ns3",
   888  			},
   889  		},
   890  	}
   891  
   892  	services14 = []*Service{
   893  		{
   894  			Hostname: "bar",
   895  			Ports:    port7443,
   896  			Attributes: ServiceAttributes{
   897  				Name:      "bar",
   898  				Namespace: "foo",
   899  			},
   900  		},
   901  	}
   902  
   903  	services15 = []*Service{
   904  		{
   905  			Hostname: "foo.svc.cluster.local",
   906  			Ports:    port7443,
   907  			Attributes: ServiceAttributes{
   908  				Name:      "foo",
   909  				Namespace: "ns1",
   910  				ExportTo:  sets.New(visibility.Private),
   911  			},
   912  		},
   913  		{
   914  			Hostname: "foo.svc.cluster.local",
   915  			Ports:    port8000,
   916  			Attributes: ServiceAttributes{
   917  				Name:      "foo",
   918  				Namespace: "ns2",
   919  			},
   920  		},
   921  		{
   922  			Hostname: "baz.svc.cluster.local",
   923  			Ports:    port7443,
   924  			Attributes: ServiceAttributes{
   925  				Name:      "baz",
   926  				Namespace: "ns3",
   927  			},
   928  		},
   929  	}
   930  
   931  	services16 = []*Service{
   932  		{
   933  			Hostname: "foo.svc.cluster.local",
   934  			Ports:    port7443,
   935  			Attributes: ServiceAttributes{
   936  				Name:      "foo",
   937  				Namespace: "ns1",
   938  			},
   939  		},
   940  		{
   941  			Hostname: "baz.svc.cluster.local",
   942  			Ports:    port7443,
   943  			Attributes: ServiceAttributes{
   944  				Name:      "baz",
   945  				Namespace: "ns3",
   946  			},
   947  		},
   948  		{
   949  			Hostname: "bar.svc.cluster.local",
   950  			Ports:    port7442,
   951  			Attributes: ServiceAttributes{
   952  				Name:      "bar",
   953  				Namespace: "ns2",
   954  			},
   955  		},
   956  		{
   957  			Hostname: "barprime.svc.cluster.local",
   958  			Ports:    port7442,
   959  			Attributes: ServiceAttributes{
   960  				Name:      "barprime",
   961  				Namespace: "ns3",
   962  			},
   963  		},
   964  		{
   965  			Hostname: "barprime.svc.cluster.local",
   966  			Ports:    port7442,
   967  			Attributes: ServiceAttributes{
   968  				Name:      "barprime",
   969  				Namespace: "ns3",
   970  			},
   971  		},
   972  		{
   973  			Hostname: "random.svc.cluster.local",
   974  			Ports:    port9999,
   975  			Attributes: ServiceAttributes{
   976  				Name:      "random",
   977  				Namespace: "randomns", // nolint
   978  			},
   979  		},
   980  	}
   981  
   982  	services17 = []*Service{
   983  		{
   984  			Hostname: "foo.svc.cluster.local",
   985  			Ports:    port7443,
   986  			Attributes: ServiceAttributes{
   987  				Name:      "foo",
   988  				Namespace: "ns1",
   989  			},
   990  		},
   991  		{
   992  			Hostname: "baz.svc.cluster.local",
   993  			Ports:    port7442,
   994  			Attributes: ServiceAttributes{
   995  				Name:      "baz",
   996  				Namespace: "ns3",
   997  			},
   998  		},
   999  	}
  1000  
  1001  	services18 = []*Service{
  1002  		{
  1003  			Hostname: "foo.svc.cluster.local",
  1004  			Ports:    port7443,
  1005  			Attributes: ServiceAttributes{
  1006  				Name:      "foo",
  1007  				Namespace: "*",
  1008  			},
  1009  		},
  1010  		{
  1011  			Hostname: "baz.svc.cluster.local",
  1012  			Ports:    port7443,
  1013  			Attributes: ServiceAttributes{
  1014  				Name:      "baz",
  1015  				Namespace: "*",
  1016  			},
  1017  		},
  1018  	}
  1019  
  1020  	services19 = []*Service{
  1021  		{
  1022  			Hostname: "en.wikipedia.org",
  1023  			Attributes: ServiceAttributes{
  1024  				Name:      "en.wikipedia.org",
  1025  				Namespace: "ns1",
  1026  			},
  1027  		},
  1028  		{
  1029  			Hostname: "*.wikipedia.org",
  1030  			Attributes: ServiceAttributes{
  1031  				Name:      "*.wikipedia.org",
  1032  				Namespace: "ns1",
  1033  			},
  1034  		},
  1035  	}
  1036  
  1037  	services20 = []*Service{
  1038  		{
  1039  			Hostname: "httpbin.org",
  1040  			Attributes: ServiceAttributes{
  1041  				Namespace: "mynamespace",
  1042  			},
  1043  		},
  1044  	}
  1045  
  1046  	services21 = []*Service{
  1047  		{
  1048  			Hostname: "foo.svc.cluster.local",
  1049  			Ports:    twoPorts,
  1050  			Attributes: ServiceAttributes{
  1051  				Name:      "foo",
  1052  				Namespace: "ns1",
  1053  			},
  1054  		},
  1055  		{
  1056  			Hostname: "baz.svc.cluster.local",
  1057  			Ports:    twoPorts,
  1058  			Attributes: ServiceAttributes{
  1059  				Name:      "baz",
  1060  				Namespace: "ns3",
  1061  			},
  1062  		},
  1063  	}
  1064  
  1065  	services22 = []*Service{
  1066  		{
  1067  			Hostname: "baz.svc.cluster.local",
  1068  			Ports:    port7443,
  1069  			Attributes: ServiceAttributes{
  1070  				Name:      "baz",
  1071  				Namespace: "ns3",
  1072  			},
  1073  		},
  1074  	}
  1075  
  1076  	services23 = []*Service{
  1077  		{
  1078  			Hostname: "foobar.svc.cluster.local",
  1079  			Ports:    port803x,
  1080  			Attributes: ServiceAttributes{
  1081  				Name:            "foo",
  1082  				Namespace:       "ns1",
  1083  				ServiceRegistry: provider.Kubernetes,
  1084  			},
  1085  		},
  1086  		{
  1087  			Hostname: "foobar.svc.cluster.local",
  1088  			Ports:    port8000,
  1089  			Attributes: ServiceAttributes{
  1090  				Name:            "foo",
  1091  				Namespace:       "ns2",
  1092  				ServiceRegistry: provider.Kubernetes,
  1093  			},
  1094  		},
  1095  		{
  1096  			Hostname: "foobar.svc.cluster.local",
  1097  			Ports:    port7443,
  1098  			Attributes: ServiceAttributes{
  1099  				Name:            "baz",
  1100  				Namespace:       "ns3",
  1101  				ServiceRegistry: provider.Kubernetes,
  1102  			},
  1103  		},
  1104  	}
  1105  	services24 = []*Service{
  1106  		{
  1107  			Hostname: "foobar.svc.cluster.local",
  1108  			Ports:    port803x,
  1109  			Attributes: ServiceAttributes{
  1110  				Name:      "foo",
  1111  				Namespace: "ns1",
  1112  			},
  1113  		},
  1114  		{
  1115  			Hostname: "foobar.svc.cluster.local",
  1116  			Ports:    port8000,
  1117  			Attributes: ServiceAttributes{
  1118  				Name:      "foo",
  1119  				Namespace: "ns2",
  1120  			},
  1121  		},
  1122  		{
  1123  			Hostname: "foobar.svc.cluster.local",
  1124  			Ports:    port7443,
  1125  			Attributes: ServiceAttributes{
  1126  				Name:      "baz",
  1127  				Namespace: "ns1", // same ns as foo
  1128  			},
  1129  		},
  1130  	}
  1131  	services25 = []*Service{
  1132  		{
  1133  			Hostname: "foobar.svc.cluster.local",
  1134  			Ports:    port803x,
  1135  			Attributes: ServiceAttributes{
  1136  				Name:      "foo",
  1137  				Namespace: "ns1",
  1138  			},
  1139  		},
  1140  		{
  1141  			Hostname: "foobar.svc.cluster.local",
  1142  			Ports:    port8000,
  1143  			Attributes: ServiceAttributes{
  1144  				Name:      "bar",
  1145  				Namespace: "ns2",
  1146  			},
  1147  		},
  1148  		{
  1149  			Hostname: "foobar.svc.cluster.local",
  1150  			Ports:    port7443,
  1151  			Attributes: ServiceAttributes{
  1152  				Name:            "baz",
  1153  				Namespace:       "ns3",
  1154  				ServiceRegistry: provider.Kubernetes,
  1155  			},
  1156  		},
  1157  	}
  1158  
  1159  	services26 = []*Service{
  1160  		{
  1161  			Hostname: "foobar.svc.cluster.local",
  1162  			Ports:    port803x,
  1163  			Attributes: ServiceAttributes{
  1164  				Name:            "foo",
  1165  				Namespace:       "ns1",
  1166  				ServiceRegistry: provider.Kubernetes,
  1167  			},
  1168  		},
  1169  	}
  1170  
  1171  	virtualServices1 = []config.Config{
  1172  		{
  1173  			Meta: config.Meta{
  1174  				GroupVersionKind: gvk.VirtualService,
  1175  				Name:             "virtualbar",
  1176  				Namespace:        "foo",
  1177  			},
  1178  			Spec: &networking.VirtualService{
  1179  				Hosts: []string{"virtualbar"},
  1180  				Http: []*networking.HTTPRoute{
  1181  					{
  1182  						Mirror: &networking.Destination{Host: "foo.svc.cluster.local"},
  1183  						Route:  []*networking.HTTPRouteDestination{{Destination: &networking.Destination{Host: "baz.svc.cluster.local"}}},
  1184  					},
  1185  				},
  1186  			},
  1187  		},
  1188  	}
  1189  
  1190  	virtualServices2 = []config.Config{
  1191  		{
  1192  			Meta: config.Meta{
  1193  				GroupVersionKind: gvk.VirtualService,
  1194  				Name:             "virtualbar",
  1195  				Namespace:        "foo",
  1196  			},
  1197  			Spec: &networking.VirtualService{
  1198  				Hosts: []string{"virtualbar", "*"},
  1199  				Http: []*networking.HTTPRoute{
  1200  					{
  1201  						Mirror: &networking.Destination{Host: "foo.svc.cluster.local"},
  1202  						Route:  []*networking.HTTPRouteDestination{{Destination: &networking.Destination{Host: "baz.svc.cluster.local"}}},
  1203  					},
  1204  				},
  1205  			},
  1206  		},
  1207  	}
  1208  
  1209  	virtualServices3 = []config.Config{
  1210  		{
  1211  			Meta: config.Meta{
  1212  				GroupVersionKind: gvk.VirtualService,
  1213  				Name:             "virtualbar",
  1214  				Namespace:        "foo",
  1215  			},
  1216  			Spec: &networking.VirtualService{
  1217  				Hosts: []string{"virtualbar"},
  1218  				Http: []*networking.HTTPRoute{
  1219  					{
  1220  						Route: []*networking.HTTPRouteDestination{
  1221  							{
  1222  								Destination: &networking.Destination{
  1223  									Host: "baz.svc.cluster.local", Port: &networking.PortSelector{Number: 7000},
  1224  								},
  1225  							},
  1226  						},
  1227  						Mirror: &networking.Destination{Host: "foo.svc.cluster.local", Port: &networking.PortSelector{Number: 7000}},
  1228  					},
  1229  				},
  1230  			},
  1231  		},
  1232  	}
  1233  
  1234  	virtualServices4 = []config.Config{
  1235  		{
  1236  			Meta: config.Meta{
  1237  				GroupVersionKind: gvk.VirtualService,
  1238  				Name:             "virtualbar",
  1239  				Namespace:        "foo",
  1240  			},
  1241  			Spec: &networking.VirtualService{
  1242  				Hosts: []string{"virtualbar"},
  1243  				Tcp: []*networking.TCPRoute{
  1244  					{
  1245  						Route: []*networking.RouteDestination{
  1246  							{
  1247  								Destination: &networking.Destination{
  1248  									Host: "baz.svc.cluster.local", Port: &networking.PortSelector{Number: 7000},
  1249  								},
  1250  							},
  1251  						},
  1252  					},
  1253  				},
  1254  			},
  1255  		},
  1256  	}
  1257  
  1258  	virtualServices5 = []config.Config{
  1259  		{
  1260  			Meta: config.Meta{
  1261  				GroupVersionKind: gvk.VirtualService,
  1262  				Name:             "virtualbar",
  1263  				Namespace:        "foo",
  1264  			},
  1265  			Spec: &networking.VirtualService{
  1266  				Hosts: []string{"virtualbar"},
  1267  				Tls: []*networking.TLSRoute{
  1268  					{
  1269  						Route: []*networking.RouteDestination{
  1270  							{
  1271  								Destination: &networking.Destination{
  1272  									Host: "baz.svc.cluster.local", Port: &networking.PortSelector{Number: 7000},
  1273  								},
  1274  							},
  1275  						},
  1276  					},
  1277  				},
  1278  			},
  1279  		},
  1280  	}
  1281  	destinationRule1 = config.Config{
  1282  		Meta: config.Meta{
  1283  			Name:      "drRule1",
  1284  			Namespace: "mynamespace",
  1285  		},
  1286  		Spec: &networking.DestinationRule{
  1287  			Host: "httpbin.org",
  1288  			WorkloadSelector: &v1beta1.WorkloadSelector{
  1289  				MatchLabels: map[string]string{"app": "app1"},
  1290  			},
  1291  			TrafficPolicy: &networking.TrafficPolicy{
  1292  				ConnectionPool: &networking.ConnectionPoolSettings{
  1293  					Http: &networking.ConnectionPoolSettings_HTTPSettings{
  1294  						MaxRetries: 33,
  1295  					},
  1296  					Tcp: &networking.ConnectionPoolSettings_TCPSettings{
  1297  						ConnectTimeout: &durationpb.Duration{Seconds: 33},
  1298  					},
  1299  				},
  1300  			},
  1301  		},
  1302  	}
  1303  	destinationRule2 = config.Config{
  1304  		Meta: config.Meta{
  1305  			Name:      "drRule2",
  1306  			Namespace: "mynamespace",
  1307  		},
  1308  		Spec: &networking.DestinationRule{
  1309  			Host: "httpbin.org",
  1310  			WorkloadSelector: &v1beta1.WorkloadSelector{
  1311  				MatchLabels: map[string]string{"app": "app2"},
  1312  			},
  1313  			TrafficPolicy: &networking.TrafficPolicy{
  1314  				ConnectionPool: &networking.ConnectionPoolSettings{
  1315  					Http: &networking.ConnectionPoolSettings_HTTPSettings{
  1316  						MaxRetries: 33,
  1317  					},
  1318  					Tcp: &networking.ConnectionPoolSettings_TCPSettings{
  1319  						ConnectTimeout: &durationpb.Duration{Seconds: 33},
  1320  					},
  1321  				},
  1322  				OutlierDetection: &networking.OutlierDetection{
  1323  					Consecutive_5XxErrors: &wrapperspb.UInt32Value{Value: 3},
  1324  				},
  1325  			},
  1326  		},
  1327  	}
  1328  	mergedDr1and3 = config.Config{
  1329  		Meta: config.Meta{
  1330  			Name:      "drRule1",
  1331  			Namespace: "mynamespace",
  1332  		},
  1333  		Spec: &networking.DestinationRule{
  1334  			Host: "httpbin.org",
  1335  			WorkloadSelector: &v1beta1.WorkloadSelector{
  1336  				MatchLabels: map[string]string{"app": "app1"},
  1337  			},
  1338  			TrafficPolicy: &networking.TrafficPolicy{
  1339  				ConnectionPool: &networking.ConnectionPoolSettings{
  1340  					Http: &networking.ConnectionPoolSettings_HTTPSettings{
  1341  						MaxRetries: 33,
  1342  					},
  1343  					Tcp: &networking.ConnectionPoolSettings_TCPSettings{
  1344  						ConnectTimeout: &durationpb.Duration{Seconds: 33},
  1345  					},
  1346  				},
  1347  			},
  1348  			Subsets: []*networking.Subset{
  1349  				{
  1350  					Name: "subset1",
  1351  				},
  1352  				{
  1353  					Name: "subset2",
  1354  				},
  1355  			},
  1356  		},
  1357  	}
  1358  	destinationRule3 = config.Config{
  1359  		Meta: config.Meta{
  1360  			Name:      "drRule3",
  1361  			Namespace: "mynamespace",
  1362  		},
  1363  		Spec: &networking.DestinationRule{
  1364  			Host: "httpbin.org",
  1365  			WorkloadSelector: &v1beta1.WorkloadSelector{
  1366  				MatchLabels: map[string]string{"app": "app1"},
  1367  			},
  1368  			Subsets: []*networking.Subset{
  1369  				{
  1370  					Name: "subset1",
  1371  				},
  1372  				{
  1373  					Name: "subset2",
  1374  				},
  1375  			},
  1376  		},
  1377  	}
  1378  	nonWorkloadSelectorDr = config.Config{
  1379  		Meta: config.Meta{
  1380  			Name:      "drRule3",
  1381  			Namespace: "mynamespace",
  1382  		},
  1383  		Spec: &networking.DestinationRule{
  1384  			Host: "httpbin.org",
  1385  			TrafficPolicy: &networking.TrafficPolicy{
  1386  				ConnectionPool: &networking.ConnectionPoolSettings{
  1387  					Http: &networking.ConnectionPoolSettings_HTTPSettings{
  1388  						MaxRetries: 33,
  1389  					},
  1390  					Tcp: &networking.ConnectionPoolSettings_TCPSettings{
  1391  						ConnectTimeout: &durationpb.Duration{Seconds: 33},
  1392  					},
  1393  				},
  1394  			},
  1395  		},
  1396  	}
  1397  )
  1398  
  1399  func TestCreateSidecarScope(t *testing.T) {
  1400  	tests := []struct {
  1401  		name          string
  1402  		sidecarConfig *config.Config
  1403  		// list of available service for a given proxy
  1404  		services        []*Service
  1405  		virtualServices []config.Config
  1406  		// list of services expected to be in the listener
  1407  		expectedServices []*Service
  1408  		expectedDr       *config.Config
  1409  	}{
  1410  		{
  1411  			"no-sidecar-config",
  1412  			nil,
  1413  			nil,
  1414  			nil,
  1415  			nil,
  1416  			nil,
  1417  		},
  1418  		{
  1419  			"no-sidecar-config-with-service",
  1420  			nil,
  1421  			services1,
  1422  			nil,
  1423  			[]*Service{
  1424  				{
  1425  					Hostname: "bar",
  1426  				},
  1427  			},
  1428  			nil,
  1429  		},
  1430  		{
  1431  			"no-sidecar-config-not-merge-service-in-diff-namespaces",
  1432  			nil,
  1433  			services23,
  1434  			nil,
  1435  			[]*Service{
  1436  				{
  1437  					Hostname: "foobar.svc.cluster.local",
  1438  					Ports:    port803x,
  1439  					Attributes: ServiceAttributes{
  1440  						Name:      "foo",
  1441  						Namespace: "ns1",
  1442  					},
  1443  				},
  1444  			},
  1445  			nil,
  1446  		},
  1447  		{
  1448  			"no-sidecar-config-merge-service-ports",
  1449  			nil,
  1450  			services24,
  1451  			nil,
  1452  			[]*Service{
  1453  				{
  1454  					Hostname: "foobar.svc.cluster.local",
  1455  					Ports:    append(port803x, port7443...),
  1456  					Attributes: ServiceAttributes{
  1457  						Name:      "foo",
  1458  						Namespace: "ns",
  1459  					},
  1460  				},
  1461  			},
  1462  			nil,
  1463  		},
  1464  		{
  1465  			"no-sidecar-config-k8s-service-take-precedence",
  1466  			nil,
  1467  			services25,
  1468  			nil,
  1469  			[]*Service{
  1470  				{
  1471  					Hostname: "foobar.svc.cluster.local",
  1472  					Ports:    port7443,
  1473  					Attributes: ServiceAttributes{
  1474  						Name:      "bar",
  1475  						Namespace: "ns2",
  1476  					},
  1477  				},
  1478  			},
  1479  			nil,
  1480  		},
  1481  		{
  1482  			"sidecar-with-multiple-egress",
  1483  			configs1,
  1484  			nil,
  1485  			nil,
  1486  			nil,
  1487  			nil,
  1488  		},
  1489  		{
  1490  			"sidecar-with-multiple-egress-with-service",
  1491  			configs1,
  1492  			services1,
  1493  			nil,
  1494  
  1495  			[]*Service{
  1496  				{
  1497  					Hostname: "bar",
  1498  				},
  1499  			},
  1500  			nil,
  1501  		},
  1502  		{
  1503  			"sidecar-with-multiple-egress-with-service-on-same-port",
  1504  			configs1,
  1505  			services3,
  1506  			nil,
  1507  			[]*Service{
  1508  				{
  1509  					Hostname: "bar",
  1510  				},
  1511  				{
  1512  					Hostname: "barprime",
  1513  				},
  1514  			},
  1515  			nil,
  1516  		},
  1517  		{
  1518  			"sidecar-with-multiple-egress-with-multiple-service",
  1519  			configs1,
  1520  			services4,
  1521  			nil,
  1522  			[]*Service{
  1523  				{
  1524  					Hostname: "bar",
  1525  				},
  1526  				{
  1527  					Hostname: "barprime",
  1528  				},
  1529  			},
  1530  			nil,
  1531  		},
  1532  		{
  1533  			"sidecar-with-zero-egress",
  1534  			configs2,
  1535  			nil,
  1536  			nil,
  1537  			nil,
  1538  			nil,
  1539  		},
  1540  		{
  1541  			"sidecar-with-zero-egress-multiple-service",
  1542  			configs2,
  1543  			services4,
  1544  			nil,
  1545  			[]*Service{
  1546  				{
  1547  					Hostname: "bar",
  1548  				},
  1549  				{
  1550  					Hostname: "barprime",
  1551  				},
  1552  			},
  1553  			nil,
  1554  		},
  1555  		{
  1556  			"sidecar-with-multiple-egress-noport",
  1557  			configs3,
  1558  			nil,
  1559  			nil,
  1560  			nil,
  1561  			nil,
  1562  		},
  1563  		{
  1564  			"sidecar-with-multiple-egress-noport-with-specific-service",
  1565  			configs3,
  1566  			services2,
  1567  			nil,
  1568  			[]*Service{
  1569  				{
  1570  					Hostname: "bar",
  1571  				},
  1572  				{
  1573  					Hostname: "barprime",
  1574  				},
  1575  			},
  1576  			nil,
  1577  		},
  1578  		{
  1579  			"sidecar-with-multiple-egress-noport-with-services",
  1580  			configs3,
  1581  			services4,
  1582  			nil,
  1583  			[]*Service{
  1584  				{
  1585  					Hostname: "bar",
  1586  				},
  1587  				{
  1588  					Hostname: "barprime",
  1589  				},
  1590  			},
  1591  			nil,
  1592  		},
  1593  		{
  1594  			"sidecar-with-egress-port-match-with-services-with-and-without-port",
  1595  			configs4,
  1596  			services5,
  1597  			nil,
  1598  			[]*Service{
  1599  				{
  1600  					Hostname: "bar",
  1601  				},
  1602  			},
  1603  			nil,
  1604  		},
  1605  		{
  1606  			"sidecar-with-egress-port-trims-service-non-matching-ports",
  1607  			configs5,
  1608  			services6,
  1609  			nil,
  1610  			[]*Service{
  1611  				{
  1612  					Hostname: "bar",
  1613  					Ports:    port8000,
  1614  				},
  1615  			},
  1616  			nil,
  1617  		},
  1618  		{
  1619  			"sidecar-with-egress-port-merges-service-ports",
  1620  			configs6,
  1621  			services6,
  1622  			nil,
  1623  			[]*Service{
  1624  				{
  1625  					Hostname: "bar",
  1626  					Ports:    twoPorts,
  1627  				},
  1628  			},
  1629  			nil,
  1630  		},
  1631  		{
  1632  			"sidecar-with-egress-port-trims-and-merges-service-ports",
  1633  			configs6,
  1634  			services7,
  1635  			nil,
  1636  			[]*Service{
  1637  				{
  1638  					Hostname: "bar",
  1639  					Ports:    twoPorts,
  1640  				},
  1641  				{
  1642  					Hostname: "barprime",
  1643  					Ports:    port8000,
  1644  				},
  1645  				{
  1646  					Hostname: "foo",
  1647  					Ports:    twoPorts,
  1648  				},
  1649  			},
  1650  			nil,
  1651  		},
  1652  		{
  1653  			"two-egresslisteners-one-with-port-and-without-port",
  1654  			configs7,
  1655  			services8,
  1656  			nil,
  1657  			[]*Service{
  1658  				{
  1659  					Hostname: "bookinginfo.com",
  1660  					Ports:    port9999,
  1661  				},
  1662  				{
  1663  					Hostname: "private.com",
  1664  				},
  1665  			},
  1666  			nil,
  1667  		},
  1668  		// Validates when service is scoped to Sidecar, it uses service port rather than listener port.
  1669  		{
  1670  			"service-port-used-while-cloning",
  1671  			configs8,
  1672  			services9,
  1673  			nil,
  1674  			[]*Service{
  1675  				{
  1676  					Hostname: "foo.svc.cluster.local",
  1677  					Ports:    port7443,
  1678  				},
  1679  			},
  1680  			nil,
  1681  		},
  1682  		{
  1683  			"wild-card-egress-listener-match",
  1684  			configs9,
  1685  			services10,
  1686  			nil,
  1687  			[]*Service{
  1688  				{
  1689  					Hostname: "foo.svc.cluster.local",
  1690  					Ports:    port7443,
  1691  				},
  1692  				{
  1693  					Hostname: "baz.svc.cluster.local",
  1694  					Ports:    port7443,
  1695  				},
  1696  				{
  1697  					Hostname: "bar.svc.cluster.local",
  1698  					Ports:    port7442,
  1699  					Attributes: ServiceAttributes{
  1700  						Name:      "bar",
  1701  						Namespace: "ns2",
  1702  					},
  1703  				},
  1704  			},
  1705  			nil,
  1706  		},
  1707  		{
  1708  			"wild-card-egress-listener-match-and-all-hosts",
  1709  			configs14,
  1710  			services16,
  1711  			nil,
  1712  			[]*Service{
  1713  				{
  1714  					Hostname: "foo.svc.cluster.local",
  1715  					Ports:    port7443,
  1716  				},
  1717  				{
  1718  					Hostname: "baz.svc.cluster.local",
  1719  					Ports:    port7443,
  1720  				},
  1721  				{
  1722  					Hostname: "bar.svc.cluster.local",
  1723  					Ports:    port7442,
  1724  					Attributes: ServiceAttributes{
  1725  						Name:      "bar",
  1726  						Namespace: "ns2",
  1727  					},
  1728  				},
  1729  				{
  1730  					Hostname: "barprime.svc.cluster.local",
  1731  					Ports:    port7442,
  1732  					Attributes: ServiceAttributes{
  1733  						Name:      "barprime",
  1734  						Namespace: "ns3",
  1735  					},
  1736  				},
  1737  				{
  1738  					Hostname: "random.svc.cluster.local",
  1739  					Ports:    port9999,
  1740  					Attributes: ServiceAttributes{
  1741  						Name:      "random",
  1742  						Namespace: "randomns", // nolint
  1743  					},
  1744  				},
  1745  			},
  1746  			nil,
  1747  		},
  1748  		{
  1749  			"wild-card-egress-listener-match-with-two-ports",
  1750  			configs9,
  1751  			services11,
  1752  			nil,
  1753  			[]*Service{
  1754  				{
  1755  					Hostname: "foo.svc.cluster.local",
  1756  					Ports:    port7443,
  1757  				},
  1758  				{
  1759  					Hostname: "baz.svc.cluster.local",
  1760  					Ports:    port7443,
  1761  				},
  1762  				{
  1763  					Hostname: "bar.svc.cluster.local",
  1764  					Ports:    twoMatchingPorts,
  1765  					Attributes: ServiceAttributes{
  1766  						Name:      "bar",
  1767  						Namespace: "ns2",
  1768  					},
  1769  				},
  1770  			},
  1771  			nil,
  1772  		},
  1773  		{
  1774  			"http-proxy-protocol-matches-any-port",
  1775  			configs10,
  1776  			services7,
  1777  			nil,
  1778  			[]*Service{
  1779  				{
  1780  					Hostname: "bar",
  1781  				},
  1782  				{
  1783  					Hostname: "barprime",
  1784  				},
  1785  				{
  1786  					Hostname: "foo",
  1787  				},
  1788  			},
  1789  			nil,
  1790  		},
  1791  		{
  1792  			"virtual-service",
  1793  			configs11,
  1794  			services11,
  1795  			virtualServices1,
  1796  			[]*Service{
  1797  				{
  1798  					Hostname: "foo.svc.cluster.local",
  1799  					Ports:    port7443,
  1800  				},
  1801  				{
  1802  					Hostname: "baz.svc.cluster.local",
  1803  					Ports:    port7443,
  1804  				},
  1805  			},
  1806  			nil,
  1807  		},
  1808  		{
  1809  			"virtual-service-destinations-matching-ports",
  1810  			configs15,
  1811  			services17,
  1812  			virtualServices1,
  1813  			[]*Service{
  1814  				{
  1815  					Hostname: "foo.svc.cluster.local",
  1816  					Ports:    port7443,
  1817  				},
  1818  			},
  1819  			nil,
  1820  		},
  1821  		{
  1822  			"virtual-service-destinations-matching-http-virtual-service-ports",
  1823  			configs21,
  1824  			services21,
  1825  			virtualServices3,
  1826  			[]*Service{
  1827  				{
  1828  					Hostname: "baz.svc.cluster.local",
  1829  					Ports:    port7000,
  1830  				},
  1831  				{
  1832  					Hostname: "foo.svc.cluster.local",
  1833  					Ports:    port7000,
  1834  				},
  1835  			},
  1836  			nil,
  1837  		},
  1838  		{
  1839  			"virtual-service-destinations-matching-tcp-virtual-service-ports",
  1840  			configs21,
  1841  			services21,
  1842  			virtualServices4,
  1843  			[]*Service{
  1844  				{
  1845  					Hostname: "baz.svc.cluster.local",
  1846  					Ports:    port7000,
  1847  				},
  1848  			},
  1849  			nil,
  1850  		},
  1851  		{
  1852  			"virtual-service-destinations-matching-tls-virtual-service-ports",
  1853  			configs21,
  1854  			services21,
  1855  			virtualServices5,
  1856  			[]*Service{
  1857  				{
  1858  					Hostname: "baz.svc.cluster.local",
  1859  					Ports:    port7000,
  1860  				},
  1861  			},
  1862  			nil,
  1863  		},
  1864  		{
  1865  			"virtual-service-prefer-required",
  1866  			configs12,
  1867  			services12,
  1868  			virtualServices1,
  1869  			[]*Service{
  1870  				{
  1871  					Hostname: "foo.svc.cluster.local",
  1872  					// Ports should not be merged even though virtual service will select the service with 7443
  1873  					// as ns1 comes before ns2, because 8000 was already picked explicitly and is in different namespace
  1874  					Ports: port8000,
  1875  				},
  1876  				{
  1877  					Hostname: "baz.svc.cluster.local",
  1878  					Ports:    port7443,
  1879  				},
  1880  			},
  1881  			nil,
  1882  		},
  1883  		{
  1884  			"virtual-service-prefer-config-namespace",
  1885  			configs11,
  1886  			services13,
  1887  			virtualServices1,
  1888  			[]*Service{
  1889  				{
  1890  					Hostname: "foo.svc.cluster.local",
  1891  					Ports:    port8000,
  1892  				},
  1893  				{
  1894  					Hostname: "baz.svc.cluster.local",
  1895  					Ports:    port7443,
  1896  				},
  1897  			},
  1898  			nil,
  1899  		},
  1900  		{
  1901  			"virtual-service-pick-alphabetical",
  1902  			configs11,
  1903  			// Ambiguous; same hostname in ns1 and ns2, neither is config namespace
  1904  			// ns1 should always win
  1905  			services12,
  1906  			virtualServices1,
  1907  			[]*Service{
  1908  				{
  1909  					Hostname: "foo.svc.cluster.local",
  1910  					Ports:    port7443,
  1911  				},
  1912  				{
  1913  					Hostname: "baz.svc.cluster.local",
  1914  					Ports:    port7443,
  1915  				},
  1916  			},
  1917  			nil,
  1918  		},
  1919  		{
  1920  			"virtual-service-pick-public",
  1921  			configs11,
  1922  			// Ambiguous; same hostname in ns1 and ns2, neither is config namespace
  1923  			// ns1 should always win
  1924  			services15,
  1925  			virtualServices1,
  1926  			[]*Service{
  1927  				{
  1928  					Hostname: "foo.svc.cluster.local",
  1929  					Ports:    port8000,
  1930  				},
  1931  				{
  1932  					Hostname: "baz.svc.cluster.local",
  1933  					Ports:    port7443,
  1934  				},
  1935  			},
  1936  			nil,
  1937  		},
  1938  		{
  1939  			"virtual-service-bad-host",
  1940  			configs11,
  1941  			services9,
  1942  			virtualServices1,
  1943  			[]*Service{
  1944  				{
  1945  					Hostname: "foo.svc.cluster.local",
  1946  					Ports:    port7443,
  1947  				},
  1948  			},
  1949  			nil,
  1950  		},
  1951  		{
  1952  			"virtual-service-destination-port-missing-from-service",
  1953  			configs21,
  1954  			services22,
  1955  			virtualServices3,
  1956  			[]*Service{},
  1957  			nil,
  1958  		},
  1959  		{
  1960  			"virtual-service-2-match-service",
  1961  			configs11,
  1962  			services18,
  1963  			virtualServices2,
  1964  			[]*Service{
  1965  				{
  1966  					Hostname: "foo.svc.cluster.local",
  1967  					Ports:    port7443,
  1968  				},
  1969  				{
  1970  					Hostname: "baz.svc.cluster.local",
  1971  					Ports:    port7443,
  1972  				},
  1973  			},
  1974  			nil,
  1975  		},
  1976  		{
  1977  			"virtual-service-2-match-service-and-domain",
  1978  			configs12,
  1979  			services18,
  1980  			virtualServices2,
  1981  			[]*Service{
  1982  				{
  1983  					Hostname: "foo.svc.cluster.local",
  1984  					Ports:    port7443,
  1985  				},
  1986  				{
  1987  					Hostname: "baz.svc.cluster.local",
  1988  					Ports:    port7443,
  1989  				},
  1990  			},
  1991  			nil,
  1992  		},
  1993  		{
  1994  			"virtual-service-2-match-all-services",
  1995  			configs15,
  1996  			services18,
  1997  			virtualServices2,
  1998  			[]*Service{
  1999  				{
  2000  					Hostname: "foo.svc.cluster.local",
  2001  					Ports:    port7443,
  2002  				},
  2003  				{
  2004  					Hostname: "baz.svc.cluster.local",
  2005  					Ports:    port7443,
  2006  				},
  2007  			},
  2008  			nil,
  2009  		},
  2010  		{
  2011  			"sidecar-scope-with-illegal-host",
  2012  			configs13,
  2013  			services14,
  2014  			nil,
  2015  			[]*Service{
  2016  				{
  2017  					Hostname: "bar",
  2018  					Ports:    port7443,
  2019  				},
  2020  			},
  2021  			nil,
  2022  		},
  2023  		{
  2024  			"sidecar-scope-with-specific-host",
  2025  			configs16,
  2026  			services19,
  2027  			nil,
  2028  			[]*Service{
  2029  				{
  2030  					Hostname: "en.wikipedia.org",
  2031  				},
  2032  			},
  2033  			nil,
  2034  		},
  2035  		{
  2036  			"sidecar-scope-with-wildcard-host",
  2037  			configs17,
  2038  			services19,
  2039  			nil,
  2040  			[]*Service{
  2041  				{
  2042  					Hostname: "en.wikipedia.org",
  2043  				},
  2044  				{
  2045  					Hostname: "*.wikipedia.org",
  2046  				},
  2047  			},
  2048  			nil,
  2049  		},
  2050  		{
  2051  			"sidecar-scope-with-matching-workloadselector-dr",
  2052  			configs18,
  2053  			services20,
  2054  			nil,
  2055  			[]*Service{
  2056  				{
  2057  					Hostname: "httpbin.org",
  2058  					Attributes: ServiceAttributes{
  2059  						Namespace: "mynamespace",
  2060  					},
  2061  				},
  2062  			},
  2063  			&destinationRule2,
  2064  		},
  2065  		{
  2066  			"sidecar-scope-with-non-matching-workloadselector-dr",
  2067  			configs19,
  2068  			services20,
  2069  			nil,
  2070  			[]*Service{
  2071  				{
  2072  					Hostname: "httpbin.org",
  2073  					Attributes: ServiceAttributes{
  2074  						Namespace: "mynamespace",
  2075  					},
  2076  				},
  2077  			},
  2078  			&nonWorkloadSelectorDr,
  2079  		},
  2080  		{
  2081  			"sidecar-scope-same-workloadselector-labels-drs-should-be-merged",
  2082  			configs20,
  2083  			services20,
  2084  			nil,
  2085  			[]*Service{
  2086  				{
  2087  					Hostname: "httpbin.org",
  2088  					Attributes: ServiceAttributes{
  2089  						Namespace: "mynamespace",
  2090  					},
  2091  				},
  2092  			},
  2093  			&mergedDr1and3,
  2094  		},
  2095  		{
  2096  			name: "multi-service-merge",
  2097  			sidecarConfig: &config.Config{
  2098  				Meta: config.Meta{
  2099  					Name:      "default",
  2100  					Namespace: "default",
  2101  				},
  2102  				Spec: &networking.Sidecar{},
  2103  			},
  2104  			services: []*Service{
  2105  				{
  2106  					Hostname: "proxy",
  2107  					Ports:    port7000,
  2108  					Attributes: ServiceAttributes{
  2109  						Name:      "s1",
  2110  						Namespace: "default",
  2111  					},
  2112  				},
  2113  				{
  2114  					Hostname: "proxy",
  2115  					Ports:    port7443,
  2116  					Attributes: ServiceAttributes{
  2117  						Name:      "s2",
  2118  						Namespace: "default",
  2119  					},
  2120  				},
  2121  				{
  2122  					Hostname: "proxy",
  2123  					Ports:    port7442,
  2124  					Attributes: ServiceAttributes{
  2125  						Name:      "s3",
  2126  						Namespace: "default",
  2127  					},
  2128  				},
  2129  			},
  2130  			expectedServices: []*Service{
  2131  				{
  2132  					Hostname: "proxy",
  2133  					Ports:    PortList{port7000[0], port7443[0], port7442[0]},
  2134  					Attributes: ServiceAttributes{
  2135  						Name:      "s1",
  2136  						Namespace: "default",
  2137  					},
  2138  				},
  2139  			},
  2140  		},
  2141  		{
  2142  			name: "k8s service take precedence over external service",
  2143  			sidecarConfig: &config.Config{
  2144  				Meta: config.Meta{
  2145  					Name:      "default",
  2146  					Namespace: "default",
  2147  				},
  2148  				Spec: &networking.Sidecar{},
  2149  			},
  2150  			services: []*Service{
  2151  				{
  2152  					Hostname: "proxy",
  2153  					Ports:    port7000,
  2154  					Attributes: ServiceAttributes{
  2155  						Name:            "s1",
  2156  						Namespace:       "default",
  2157  						ServiceRegistry: provider.External,
  2158  					},
  2159  				},
  2160  				{
  2161  					Hostname: "proxy",
  2162  					Ports:    port7443,
  2163  					Attributes: ServiceAttributes{
  2164  						Name:            "s2",
  2165  						Namespace:       "default",
  2166  						ServiceRegistry: provider.External,
  2167  					},
  2168  				},
  2169  				{
  2170  					Hostname: "proxy",
  2171  					Ports:    port7442,
  2172  					Attributes: ServiceAttributes{
  2173  						Name:            "s3",
  2174  						Namespace:       "default",
  2175  						ServiceRegistry: provider.Kubernetes,
  2176  					},
  2177  				},
  2178  			},
  2179  			expectedServices: []*Service{
  2180  				{
  2181  					Hostname: "proxy",
  2182  					Ports:    port7442,
  2183  					Attributes: ServiceAttributes{
  2184  						Name:            "s3",
  2185  						Namespace:       "default",
  2186  						ServiceRegistry: provider.Kubernetes,
  2187  					},
  2188  				},
  2189  			},
  2190  		},
  2191  		{
  2192  			name: "k8s service take precedence over external service, but not over k8s service",
  2193  			sidecarConfig: &config.Config{
  2194  				Meta: config.Meta{
  2195  					Name:      "default",
  2196  					Namespace: "default",
  2197  				},
  2198  				Spec: &networking.Sidecar{},
  2199  			},
  2200  			services: []*Service{
  2201  				{
  2202  					Hostname: "proxy",
  2203  					Ports:    port7000,
  2204  					Attributes: ServiceAttributes{
  2205  						Name:            "s1",
  2206  						Namespace:       "default",
  2207  						ServiceRegistry: provider.External,
  2208  					},
  2209  				},
  2210  				{
  2211  					Hostname: "proxy",
  2212  					Ports:    port7443,
  2213  					Attributes: ServiceAttributes{
  2214  						Name:            "s2",
  2215  						Namespace:       "default",
  2216  						ServiceRegistry: provider.Kubernetes,
  2217  					},
  2218  				},
  2219  				{
  2220  					Hostname: "proxy",
  2221  					Ports:    port7442,
  2222  					Attributes: ServiceAttributes{
  2223  						Name:            "s3",
  2224  						Namespace:       "default",
  2225  						ServiceRegistry: provider.Kubernetes,
  2226  					},
  2227  				},
  2228  			},
  2229  			expectedServices: []*Service{
  2230  				{
  2231  					Hostname: "proxy",
  2232  					Ports:    port744x,
  2233  					Attributes: ServiceAttributes{
  2234  						Name:            "s2",
  2235  						Namespace:       "default",
  2236  						ServiceRegistry: provider.Kubernetes,
  2237  					},
  2238  				},
  2239  			},
  2240  		},
  2241  		{
  2242  			name:          "multi-port-merge",
  2243  			sidecarConfig: configs22,
  2244  			services:      services23,
  2245  			expectedServices: []*Service{
  2246  				{
  2247  					Hostname: "foobar.svc.cluster.local",
  2248  					Ports:    port803x,
  2249  					Attributes: ServiceAttributes{
  2250  						Name:      "foo",
  2251  						Namespace: "ns1",
  2252  					},
  2253  				},
  2254  			},
  2255  		},
  2256  		{
  2257  			name:          "multi-port-merge-in-same-namespace",
  2258  			sidecarConfig: configs23,
  2259  			services:      services26,
  2260  			expectedServices: []*Service{
  2261  				{
  2262  					Hostname: "foobar.svc.cluster.local",
  2263  					Ports:    port803x,
  2264  					Attributes: ServiceAttributes{
  2265  						Name:      "foo",
  2266  						Namespace: "ns1",
  2267  					},
  2268  				},
  2269  			},
  2270  		},
  2271  		{
  2272  			name:          "multi-port-merge: serviceentry not merge with another namespace",
  2273  			sidecarConfig: configs22,
  2274  			services: []*Service{
  2275  				{
  2276  					Hostname: "foobar.svc.cluster.local",
  2277  					Ports:    port803x[:3],
  2278  					Attributes: ServiceAttributes{
  2279  						Name:      "foo",
  2280  						Namespace: "ns1",
  2281  					},
  2282  				},
  2283  				{
  2284  					Hostname: "foobar.svc.cluster.local",
  2285  					Ports:    port803x[3:],
  2286  					Attributes: ServiceAttributes{
  2287  						Name:      "bar",
  2288  						Namespace: "ns2",
  2289  					},
  2290  				},
  2291  				{
  2292  					Hostname: "foobar.svc.cluster.local",
  2293  					Ports:    port7443,
  2294  					Attributes: ServiceAttributes{
  2295  						Name:      "baz",
  2296  						Namespace: "ns3",
  2297  					},
  2298  				},
  2299  			},
  2300  			expectedServices: []*Service{
  2301  				{
  2302  					Hostname: "foobar.svc.cluster.local",
  2303  					Ports:    port803x[:3],
  2304  					Attributes: ServiceAttributes{
  2305  						Name:      "foo",
  2306  						Namespace: "ns1",
  2307  					},
  2308  				},
  2309  			},
  2310  		},
  2311  		{
  2312  			name:          "multi-port-merge: k8s service take precedence",
  2313  			sidecarConfig: configs22,
  2314  			services: []*Service{
  2315  				{
  2316  					Hostname: "foobar.svc.cluster.local",
  2317  					Ports:    port803x,
  2318  					Attributes: ServiceAttributes{
  2319  						Name:      "foo",
  2320  						Namespace: "ns1",
  2321  					},
  2322  				},
  2323  				{
  2324  					Hostname: "foobar.svc.cluster.local",
  2325  					Ports:    port803x,
  2326  					Attributes: ServiceAttributes{
  2327  						Name:            "bar",
  2328  						Namespace:       "ns2",
  2329  						ServiceRegistry: provider.Kubernetes,
  2330  					},
  2331  				},
  2332  				{
  2333  					Hostname: "foobar.svc.cluster.local",
  2334  					Ports:    port7443,
  2335  					Attributes: ServiceAttributes{
  2336  						Name:      "baz",
  2337  						Namespace: "ns3",
  2338  					},
  2339  				},
  2340  			},
  2341  			expectedServices: []*Service{
  2342  				{
  2343  					Hostname: "foobar.svc.cluster.local",
  2344  					Ports:    port803x,
  2345  					Attributes: ServiceAttributes{
  2346  						Name:      "bar",
  2347  						Namespace: "ns2",
  2348  					},
  2349  				},
  2350  			},
  2351  		},
  2352  		{
  2353  			name:          "multi-port-merge: serviceentry merge",
  2354  			sidecarConfig: configs22,
  2355  			services: []*Service{
  2356  				{
  2357  					Hostname: "foobar.svc.cluster.local",
  2358  					Ports:    port803x[:3],
  2359  					Attributes: ServiceAttributes{
  2360  						Name:      "foo",
  2361  						Namespace: "ns1",
  2362  					},
  2363  				},
  2364  				{
  2365  					Hostname: "foobar.svc.cluster.local",
  2366  					Ports:    port803x[3:],
  2367  					Attributes: ServiceAttributes{
  2368  						Name:      "bar",
  2369  						Namespace: "ns1",
  2370  					},
  2371  				},
  2372  				{
  2373  					Hostname: "foobar.svc.cluster.local",
  2374  					Ports:    port7443,
  2375  					Attributes: ServiceAttributes{
  2376  						Name:      "baz",
  2377  						Namespace: "ns3",
  2378  					},
  2379  				},
  2380  			},
  2381  			expectedServices: []*Service{
  2382  				{
  2383  					Hostname: "foobar.svc.cluster.local",
  2384  					Ports:    port803x,
  2385  					Attributes: ServiceAttributes{
  2386  						Name:      "foo",
  2387  						Namespace: "ns1",
  2388  					},
  2389  				},
  2390  			},
  2391  		},
  2392  		{
  2393  			name:          "serviceentry not merge when resolution is different",
  2394  			sidecarConfig: configs22,
  2395  			services: []*Service{
  2396  				{
  2397  					Hostname: "foobar.svc.cluster.local",
  2398  					Ports:    port803x[:3],
  2399  					Attributes: ServiceAttributes{
  2400  						Name:      "foo",
  2401  						Namespace: "ns1",
  2402  					},
  2403  				},
  2404  				{
  2405  					Hostname:   "foobar.svc.cluster.local",
  2406  					Ports:      port803x[3:],
  2407  					Resolution: DNSLB,
  2408  					Attributes: ServiceAttributes{
  2409  						Name:      "bar",
  2410  						Namespace: "ns1",
  2411  					},
  2412  				},
  2413  			},
  2414  			expectedServices: []*Service{
  2415  				{
  2416  					Hostname: "foobar.svc.cluster.local",
  2417  					Ports:    port803x[:3],
  2418  					Attributes: ServiceAttributes{
  2419  						Name:      "foo",
  2420  						Namespace: "ns1",
  2421  					},
  2422  				},
  2423  			},
  2424  		},
  2425  		{
  2426  			name:          "serviceentry not merge when label selector is different",
  2427  			sidecarConfig: configs22,
  2428  			services: []*Service{
  2429  				{
  2430  					Hostname: "foobar.svc.cluster.local",
  2431  					Ports:    port803x[:3],
  2432  					Attributes: ServiceAttributes{
  2433  						Name:      "foo",
  2434  						Namespace: "ns1",
  2435  						LabelSelectors: map[string]string{
  2436  							"app": "foo",
  2437  						},
  2438  					},
  2439  				},
  2440  				{
  2441  					Hostname:   "foobar.svc.cluster.local",
  2442  					Ports:      port803x[3:],
  2443  					Resolution: DNSLB,
  2444  					Attributes: ServiceAttributes{
  2445  						Name:      "bar",
  2446  						Namespace: "ns1",
  2447  						LabelSelectors: map[string]string{
  2448  							"app": "bar",
  2449  						},
  2450  					},
  2451  				},
  2452  			},
  2453  			expectedServices: []*Service{
  2454  				{
  2455  					Hostname: "foobar.svc.cluster.local",
  2456  					Ports:    port803x[:3],
  2457  					Attributes: ServiceAttributes{
  2458  						Name:      "foo",
  2459  						Namespace: "ns1",
  2460  						LabelSelectors: map[string]string{
  2461  							"app": "foo",
  2462  						},
  2463  					},
  2464  				},
  2465  			},
  2466  		},
  2467  		{
  2468  			name:          "serviceentry not merge when exportTo is different",
  2469  			sidecarConfig: configs22,
  2470  			services: []*Service{
  2471  				{
  2472  					Hostname: "foobar.svc.cluster.local",
  2473  					Ports:    port803x[:3],
  2474  					Attributes: ServiceAttributes{
  2475  						Name:      "foo",
  2476  						Namespace: "ns1",
  2477  						ExportTo:  sets.New(visibility.Public),
  2478  					},
  2479  				},
  2480  				{
  2481  					Hostname:   "foobar.svc.cluster.local",
  2482  					Ports:      port803x[3:],
  2483  					Resolution: DNSLB,
  2484  					Attributes: ServiceAttributes{
  2485  						Name:      "bar",
  2486  						Namespace: "ns1",
  2487  						ExportTo:  sets.New(visibility.Private),
  2488  					},
  2489  				},
  2490  			},
  2491  			expectedServices: []*Service{
  2492  				{
  2493  					Hostname: "foobar.svc.cluster.local",
  2494  					Ports:    port803x[:3],
  2495  					Attributes: ServiceAttributes{
  2496  						Name:      "foo",
  2497  						Namespace: "ns1",
  2498  						ExportTo:  sets.New(visibility.Public),
  2499  					},
  2500  				},
  2501  			},
  2502  		},
  2503  	}
  2504  
  2505  	for _, tt := range tests {
  2506  		t.Run(tt.name, func(t *testing.T) {
  2507  			var serviceFound bool
  2508  			var portsMatched bool
  2509  			ps := NewPushContext()
  2510  			meshConfig := mesh.DefaultMeshConfig()
  2511  			ps.Mesh = meshConfig
  2512  			ps.setDestinationRules([]config.Config{destinationRule1, destinationRule2, destinationRule3, nonWorkloadSelectorDr})
  2513  			if tt.services != nil {
  2514  				ps.ServiceIndex.public = append(ps.ServiceIndex.public, tt.services...)
  2515  
  2516  				for _, s := range tt.services {
  2517  					if _, f := ps.ServiceIndex.HostnameAndNamespace[s.Hostname]; !f {
  2518  						ps.ServiceIndex.HostnameAndNamespace[s.Hostname] = map[string]*Service{}
  2519  					}
  2520  					ps.ServiceIndex.HostnameAndNamespace[s.Hostname][s.Attributes.Namespace] = s
  2521  				}
  2522  			}
  2523  			if tt.virtualServices != nil {
  2524  				// nolint lll
  2525  				ps.virtualServiceIndex.publicByGateway[constants.IstioMeshGateway] = append(ps.virtualServiceIndex.publicByGateway[constants.IstioMeshGateway], tt.virtualServices...)
  2526  			}
  2527  
  2528  			ps.exportToDefaults = exportToDefaults{
  2529  				virtualService:  sets.New(visibility.Public),
  2530  				service:         sets.New(visibility.Public),
  2531  				destinationRule: sets.New(visibility.Public),
  2532  			}
  2533  
  2534  			sidecarConfig := tt.sidecarConfig
  2535  			configuredListeneres := 1
  2536  			if sidecarConfig != nil {
  2537  				r := sidecarConfig.Spec.(*networking.Sidecar)
  2538  				if len(r.Egress) > 0 {
  2539  					configuredListeneres = len(r.Egress)
  2540  				}
  2541  			}
  2542  
  2543  			sidecarScope := convertToSidecarScope(ps, sidecarConfig, "mynamespace")
  2544  
  2545  			numberListeners := len(sidecarScope.EgressListeners)
  2546  			if numberListeners != configuredListeneres {
  2547  				t.Errorf("Expected %d listeners, Got: %d", configuredListeneres, numberListeners)
  2548  			}
  2549  
  2550  			if sidecarConfig == nil {
  2551  				services := sidecarScope.EgressListeners[0].services
  2552  				if !reflect.DeepEqual(services, sidecarScope.services) {
  2553  					t.Errorf("services in default egress listener not equals sidecar scope services: %v",
  2554  						cmp.Diff(services, sidecarScope.services, cmpopts.IgnoreFields(AddressMap{}, "mutex")))
  2555  				}
  2556  			}
  2557  
  2558  			for _, s1 := range sidecarScope.services {
  2559  				serviceFound = false
  2560  				portsMatched = false
  2561  				var ports PortList
  2562  				for _, s2 := range tt.expectedServices {
  2563  					if s1.Hostname == s2.Hostname {
  2564  						serviceFound = true
  2565  						if len(s2.Ports) > 0 {
  2566  							if reflect.DeepEqual(s2.Ports, s1.Ports) {
  2567  								portsMatched = true
  2568  							} else {
  2569  								ports = s2.Ports
  2570  							}
  2571  						}
  2572  						break
  2573  					}
  2574  				}
  2575  				if !serviceFound {
  2576  					t.Errorf("Expected service %v in SidecarScope but not found", s1.Hostname)
  2577  				} else if len(ports) > 0 && !portsMatched {
  2578  					t.Errorf("Expected service %v found in SidecarScope but ports not merged correctly. want: %v, got: %v", s1.Hostname, ports, s1.Ports)
  2579  				}
  2580  
  2581  				// validate service is also in sidecarScope.serviceByHostname
  2582  				if s2, ok := sidecarScope.servicesByHostname[s1.Hostname]; !ok {
  2583  					t.Errorf("Expected service %v should also in servicesByHostname", s1.Hostname)
  2584  				} else if s1 != s2 {
  2585  					t.Errorf("Expected service %v in SidecarScope.Services should equal to that in SidecarScope.servicesByHostname", s1.Hostname)
  2586  				}
  2587  			}
  2588  
  2589  			for _, s1 := range tt.expectedServices {
  2590  				serviceFound = false
  2591  				for _, s2 := range sidecarScope.services {
  2592  					if s1.Hostname == s2.Hostname {
  2593  						serviceFound = true
  2594  						break
  2595  					}
  2596  				}
  2597  				if !serviceFound {
  2598  					t.Errorf("UnExpected service %v in SidecarScope", s1.Hostname)
  2599  				}
  2600  			}
  2601  
  2602  			if tt.sidecarConfig != nil {
  2603  				dr := sidecarScope.DestinationRule(TrafficDirectionOutbound,
  2604  					&Proxy{
  2605  						Labels:          tt.sidecarConfig.Labels,
  2606  						Metadata:        &NodeMetadata{Labels: tt.sidecarConfig.Labels},
  2607  						ConfigNamespace: tt.sidecarConfig.Namespace,
  2608  					}, host.Name("httpbin.org")).GetRule()
  2609  				assert.Equal(t, dr, tt.expectedDr)
  2610  			}
  2611  		})
  2612  	}
  2613  }
  2614  
  2615  func TestIstioEgressListenerWrapper(t *testing.T) {
  2616  	serviceA8000 := &Service{
  2617  		Hostname:   "host",
  2618  		Ports:      port8000,
  2619  		Attributes: ServiceAttributes{Namespace: "a"},
  2620  	}
  2621  	serviceA9000 := &Service{
  2622  		Hostname:   "host",
  2623  		Ports:      port9000,
  2624  		Attributes: ServiceAttributes{Namespace: "a"},
  2625  	}
  2626  	serviceAalt := &Service{
  2627  		Hostname:   "alt",
  2628  		Ports:      port8000,
  2629  		Attributes: ServiceAttributes{Namespace: "a"},
  2630  	}
  2631  
  2632  	serviceB8000 := &Service{
  2633  		Hostname:   "host",
  2634  		Ports:      port8000,
  2635  		Attributes: ServiceAttributes{Namespace: "b"},
  2636  	}
  2637  	serviceB9000 := &Service{
  2638  		Hostname:   "host",
  2639  		Ports:      port9000,
  2640  		Attributes: ServiceAttributes{Namespace: "b"},
  2641  	}
  2642  	serviceBalt := &Service{
  2643  		Hostname:   "alt",
  2644  		Ports:      port8000,
  2645  		Attributes: ServiceAttributes{Namespace: "b"},
  2646  	}
  2647  
  2648  	serviceBWildcard := &Service{
  2649  		Hostname:   "*.test.wildcard.com",
  2650  		Ports:      port8000,
  2651  		Attributes: ServiceAttributes{Namespace: "b"},
  2652  	}
  2653  	allServices := []*Service{serviceA8000, serviceA9000, serviceAalt, serviceB8000, serviceB9000, serviceBalt}
  2654  
  2655  	tests := []struct {
  2656  		name          string
  2657  		listenerHosts map[string]hostClassification
  2658  		services      []*Service
  2659  		expected      []*Service
  2660  		namespace     string
  2661  	}{
  2662  		{
  2663  			name: "*/* imports only those in a",
  2664  			listenerHosts: map[string]hostClassification{
  2665  				wildcardNamespace: {allHosts: []host.Name{wildcardService}, exactHosts: sets.New[host.Name]()},
  2666  			},
  2667  			services:  allServices,
  2668  			expected:  []*Service{serviceA8000, serviceA9000, serviceAalt},
  2669  			namespace: "a",
  2670  		},
  2671  		{
  2672  			name: "*/* will bias towards configNamespace",
  2673  			listenerHosts: map[string]hostClassification{
  2674  				wildcardNamespace: {allHosts: []host.Name{wildcardService}, exactHosts: sets.New[host.Name]()},
  2675  			},
  2676  			services:  []*Service{serviceB8000, serviceB9000, serviceBalt, serviceA8000, serviceA9000, serviceAalt},
  2677  			expected:  []*Service{serviceA8000, serviceA9000, serviceAalt},
  2678  			namespace: "a",
  2679  		},
  2680  		{
  2681  			name: "a/* imports only those in a",
  2682  			listenerHosts: map[string]hostClassification{
  2683  				"a": {allHosts: []host.Name{wildcardService}, exactHosts: sets.New[host.Name]()},
  2684  			},
  2685  			services:  allServices,
  2686  			expected:  []*Service{serviceA8000, serviceA9000, serviceAalt},
  2687  			namespace: "a",
  2688  		},
  2689  		{
  2690  			name: "b/*, b/* imports only those in b",
  2691  			listenerHosts: map[string]hostClassification{
  2692  				"b": {allHosts: []host.Name{wildcardService, wildcardService}, exactHosts: sets.New[host.Name]()},
  2693  			},
  2694  			services:  allServices,
  2695  			expected:  []*Service{serviceB8000, serviceB9000, serviceBalt},
  2696  			namespace: "a",
  2697  		},
  2698  		{
  2699  			name: "*/alt imports alt in namespace a",
  2700  			listenerHosts: map[string]hostClassification{
  2701  				wildcardNamespace: {allHosts: []host.Name{"alt"}, exactHosts: sets.New[host.Name]("alt")},
  2702  			},
  2703  			services:  allServices,
  2704  			expected:  []*Service{serviceAalt},
  2705  			namespace: "a",
  2706  		},
  2707  		{
  2708  			name: "b/alt imports alt in a namespaces",
  2709  			listenerHosts: map[string]hostClassification{
  2710  				"b": {allHosts: []host.Name{"alt"}, exactHosts: sets.New[host.Name]("alt")},
  2711  			},
  2712  			services:  allServices,
  2713  			expected:  []*Service{serviceBalt},
  2714  			namespace: "a",
  2715  		},
  2716  		{
  2717  			name: "b/* imports doesn't import in namespace a with proxy in a",
  2718  			listenerHosts: map[string]hostClassification{
  2719  				"b": {allHosts: []host.Name{wildcardService}, exactHosts: sets.New[host.Name]()},
  2720  			},
  2721  			services:  []*Service{serviceA8000},
  2722  			expected:  []*Service{},
  2723  			namespace: "a",
  2724  		},
  2725  		{
  2726  			name: "multiple hosts selected same service",
  2727  			listenerHosts: map[string]hostClassification{
  2728  				"a": {allHosts: []host.Name{wildcardService}, exactHosts: sets.New[host.Name]()},
  2729  				"*": {allHosts: []host.Name{wildcardService}, exactHosts: sets.New[host.Name]()},
  2730  			},
  2731  			services:  []*Service{serviceA8000},
  2732  			expected:  []*Service{serviceA8000},
  2733  			namespace: "a",
  2734  		},
  2735  		{
  2736  			name: "fall back to wildcard namespace",
  2737  			listenerHosts: map[string]hostClassification{
  2738  				wildcardNamespace: {allHosts: []host.Name{"host"}, exactHosts: sets.New[host.Name]("host")},
  2739  				"a":               {allHosts: []host.Name{"alt"}, exactHosts: sets.New[host.Name]("alt")},
  2740  			},
  2741  			services:  allServices,
  2742  			expected:  []*Service{serviceA8000, serviceA9000, serviceAalt},
  2743  			namespace: "a",
  2744  		},
  2745  		{
  2746  			name: "service is wildcard, but not listener's subset",
  2747  			listenerHosts: map[string]hostClassification{
  2748  				"b": {allHosts: []host.Name{"wildcard.com"}, exactHosts: sets.New[host.Name]("wildcard.com")},
  2749  			},
  2750  			services:  []*Service{serviceBWildcard},
  2751  			expected:  []*Service{},
  2752  			namespace: "b",
  2753  		},
  2754  		{
  2755  			name: "service is wildcard",
  2756  			listenerHosts: map[string]hostClassification{
  2757  				"b": {allHosts: []host.Name{"*.wildcard.com"}, exactHosts: sets.New[host.Name]()},
  2758  			},
  2759  			services:  []*Service{serviceBWildcard},
  2760  			expected:  []*Service{serviceBWildcard},
  2761  			namespace: "b",
  2762  		},
  2763  	}
  2764  
  2765  	for _, tt := range tests {
  2766  		t.Run(tt.name, func(t *testing.T) {
  2767  			ilw := &IstioEgressListenerWrapper{}
  2768  			got := ilw.selectServices(tt.services, tt.namespace, tt.listenerHosts)
  2769  			if !reflect.DeepEqual(got, tt.expected) {
  2770  				gots, _ := json.MarshalIndent(got, "", "  ")
  2771  				expecteds, _ := json.MarshalIndent(tt.expected, "", "  ")
  2772  				t.Errorf("Got %v, expected %v", string(gots), string(expecteds))
  2773  			}
  2774  		})
  2775  	}
  2776  }
  2777  
  2778  func TestContainsEgressDependencies(t *testing.T) {
  2779  	const (
  2780  		svcName = "svc1.com"
  2781  		nsName  = "ns"
  2782  		drName  = "dr1"
  2783  		vsName  = "vs1"
  2784  	)
  2785  
  2786  	allContains := func(ns string, contains bool) map[ConfigKey]bool {
  2787  		return map[ConfigKey]bool{
  2788  			{kind.ServiceEntry, svcName, ns}:   contains,
  2789  			{kind.VirtualService, vsName, ns}:  contains,
  2790  			{kind.DestinationRule, drName, ns}: contains,
  2791  		}
  2792  	}
  2793  
  2794  	cases := []struct {
  2795  		name   string
  2796  		egress []string
  2797  
  2798  		contains map[ConfigKey]bool
  2799  	}{
  2800  		{"Just wildcard", []string{"*/*"}, allContains(nsName, true)},
  2801  		{"Namespace and wildcard", []string{"ns/*", "*/*"}, allContains(nsName, true)},
  2802  		{"Just Namespace", []string{"ns/*"}, allContains(nsName, true)},
  2803  		{"Wrong Namespace", []string{"ns/*"}, allContains("other-ns", false)},
  2804  		{"No Sidecar", nil, allContains("ns", true)},
  2805  		{"No Sidecar Other Namespace", nil, allContains("other-ns", false)},
  2806  		{"clusterScope resource", []string{"*/*"}, map[ConfigKey]bool{
  2807  			{kind.AuthorizationPolicy, "authz", "default"}: true,
  2808  		}},
  2809  	}
  2810  	for _, tt := range cases {
  2811  		t.Run(tt.name, func(t *testing.T) {
  2812  			cfg := &config.Config{
  2813  				Meta: config.Meta{
  2814  					Name:      "foo",
  2815  					Namespace: "default",
  2816  				},
  2817  				Spec: &networking.Sidecar{
  2818  					Egress: []*networking.IstioEgressListener{
  2819  						{
  2820  							Hosts: tt.egress,
  2821  						},
  2822  					},
  2823  				},
  2824  			}
  2825  			ps := NewPushContext()
  2826  			meshConfig := mesh.DefaultMeshConfig()
  2827  			ps.Mesh = meshConfig
  2828  
  2829  			services := []*Service{
  2830  				{
  2831  					Hostname:   "nomatch",
  2832  					Attributes: ServiceAttributes{Namespace: "nomatch"},
  2833  				},
  2834  				{
  2835  					Hostname:   svcName,
  2836  					Attributes: ServiceAttributes{Namespace: nsName},
  2837  				},
  2838  			}
  2839  			virtualServices := []config.Config{
  2840  				{
  2841  					Meta: config.Meta{
  2842  						Name:      vsName,
  2843  						Namespace: nsName,
  2844  					},
  2845  					Spec: &networking.VirtualService{
  2846  						Hosts: []string{svcName},
  2847  					},
  2848  				},
  2849  			}
  2850  			destinationRules := []config.Config{
  2851  				{
  2852  					Meta: config.Meta{
  2853  						Name:      drName,
  2854  						Namespace: nsName,
  2855  					},
  2856  					Spec: &networking.DestinationRule{
  2857  						Host:     svcName,
  2858  						ExportTo: []string{"*"},
  2859  					},
  2860  				},
  2861  			}
  2862  			ps.ServiceIndex.public = append(ps.ServiceIndex.public, services...)
  2863  			// nolint lll
  2864  			ps.virtualServiceIndex.publicByGateway[constants.IstioMeshGateway] = append(ps.virtualServiceIndex.publicByGateway[constants.IstioMeshGateway], virtualServices...)
  2865  			ps.setDestinationRules(destinationRules)
  2866  			sidecarScope := convertToSidecarScope(ps, cfg, "default")
  2867  			if len(tt.egress) == 0 {
  2868  				sidecarScope = DefaultSidecarScopeForNamespace(ps, "default")
  2869  			}
  2870  
  2871  			for k, v := range tt.contains {
  2872  				if ok := sidecarScope.DependsOnConfig(k, ps.Mesh.RootNamespace); ok != v {
  2873  					t.Fatalf("Expected contains %v-%v, but no match", k, v)
  2874  				}
  2875  			}
  2876  		})
  2877  	}
  2878  }
  2879  
  2880  func TestRootNsSidecarDependencies(t *testing.T) {
  2881  	cases := []struct {
  2882  		name   string
  2883  		egress []string
  2884  
  2885  		contains map[ConfigKey]bool
  2886  	}{
  2887  		{"AuthorizationPolicy in the same ns as workload", []string{"*/*"}, map[ConfigKey]bool{
  2888  			{kind.AuthorizationPolicy, "authz", "default"}: true,
  2889  		}},
  2890  		{"AuthorizationPolicy in a different ns from workload", []string{"*/*"}, map[ConfigKey]bool{
  2891  			{kind.AuthorizationPolicy, "authz", "ns1"}: false,
  2892  		}},
  2893  		{"AuthorizationPolicy in the root namespace", []string{"*/*"}, map[ConfigKey]bool{
  2894  			{kind.AuthorizationPolicy, "authz", constants.IstioSystemNamespace}: true,
  2895  		}},
  2896  		{"WasmPlugin in same ns as workload", []string{"*/*"}, map[ConfigKey]bool{
  2897  			{kind.WasmPlugin, "wasm", "default"}: true,
  2898  		}},
  2899  		{"WasmPlugin in different ns from workload", []string{"*/*"}, map[ConfigKey]bool{
  2900  			{kind.WasmPlugin, "wasm", "ns1"}: false,
  2901  		}},
  2902  		{"WasmPlugin in the root namespace", []string{"*/*"}, map[ConfigKey]bool{
  2903  			{kind.WasmPlugin, "wasm", constants.IstioSystemNamespace}: true,
  2904  		}},
  2905  	}
  2906  
  2907  	for _, tt := range cases {
  2908  		t.Run(tt.name, func(t *testing.T) {
  2909  			cfg := &config.Config{
  2910  				Meta: config.Meta{
  2911  					Name:      "foo",
  2912  					Namespace: constants.IstioSystemNamespace,
  2913  				},
  2914  				Spec: &networking.Sidecar{
  2915  					Egress: []*networking.IstioEgressListener{
  2916  						{
  2917  							Hosts: tt.egress,
  2918  						},
  2919  					},
  2920  				},
  2921  			}
  2922  			ps := NewPushContext()
  2923  			meshConfig := mesh.DefaultMeshConfig()
  2924  			ps.Mesh = meshConfig
  2925  			sidecarScope := convertToSidecarScope(ps, cfg, "default")
  2926  			if len(tt.egress) == 0 {
  2927  				sidecarScope = DefaultSidecarScopeForNamespace(ps, "default")
  2928  			}
  2929  
  2930  			for k, v := range tt.contains {
  2931  				if ok := sidecarScope.DependsOnConfig(k, ps.Mesh.RootNamespace); ok != v {
  2932  					t.Fatalf("Expected contains %v-%v, but no match", k, v)
  2933  				}
  2934  			}
  2935  		})
  2936  	}
  2937  }
  2938  
  2939  func TestSidecarOutboundTrafficPolicy(t *testing.T) {
  2940  	configWithoutOutboundTrafficPolicy := &config.Config{
  2941  		Meta: config.Meta{
  2942  			Name:      "foo",
  2943  			Namespace: "not-default",
  2944  		},
  2945  		Spec: &networking.Sidecar{},
  2946  	}
  2947  	configRegistryOnly := &config.Config{
  2948  		Meta: config.Meta{
  2949  			Name:      "foo",
  2950  			Namespace: "not-default",
  2951  		},
  2952  		Spec: &networking.Sidecar{
  2953  			OutboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  2954  				Mode: networking.OutboundTrafficPolicy_REGISTRY_ONLY,
  2955  			},
  2956  		},
  2957  	}
  2958  	configAllowAny := &config.Config{
  2959  		Meta: config.Meta{
  2960  			Name:      "foo",
  2961  			Namespace: "not-default",
  2962  		},
  2963  		Spec: &networking.Sidecar{
  2964  			OutboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  2965  				Mode: networking.OutboundTrafficPolicy_ALLOW_ANY,
  2966  			},
  2967  		},
  2968  	}
  2969  
  2970  	meshConfigWithRegistryOnly, err := mesh.ApplyMeshConfigDefaults(`
  2971  outboundTrafficPolicy:
  2972    mode: REGISTRY_ONLY
  2973  `)
  2974  	if err != nil {
  2975  		t.Fatalf("unexpected error reading test mesh config: %v", err)
  2976  	}
  2977  
  2978  	tests := []struct {
  2979  		name                  string
  2980  		meshConfig            *v1alpha1.MeshConfig
  2981  		sidecar               *config.Config
  2982  		outboundTrafficPolicy *networking.OutboundTrafficPolicy
  2983  	}{
  2984  		{
  2985  			name:       "default MeshConfig, no Sidecar",
  2986  			meshConfig: mesh.DefaultMeshConfig(),
  2987  			sidecar:    nil,
  2988  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  2989  				Mode: networking.OutboundTrafficPolicy_ALLOW_ANY,
  2990  			},
  2991  		},
  2992  		{
  2993  			name:       "default MeshConfig, sidecar without OutboundTrafficPolicy",
  2994  			meshConfig: mesh.DefaultMeshConfig(),
  2995  			sidecar:    configWithoutOutboundTrafficPolicy,
  2996  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  2997  				Mode: networking.OutboundTrafficPolicy_ALLOW_ANY,
  2998  			},
  2999  		},
  3000  		{
  3001  			name:       "default MeshConfig, Sidecar with registry only",
  3002  			meshConfig: mesh.DefaultMeshConfig(),
  3003  			sidecar:    configRegistryOnly,
  3004  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  3005  				Mode: networking.OutboundTrafficPolicy_REGISTRY_ONLY,
  3006  			},
  3007  		},
  3008  		{
  3009  			name:       "default MeshConfig, Sidecar with allow any",
  3010  			meshConfig: mesh.DefaultMeshConfig(),
  3011  			sidecar:    configAllowAny,
  3012  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  3013  				Mode: networking.OutboundTrafficPolicy_ALLOW_ANY,
  3014  			},
  3015  		},
  3016  		{
  3017  			name:       "MeshConfig registry only, no Sidecar",
  3018  			meshConfig: meshConfigWithRegistryOnly,
  3019  			sidecar:    nil,
  3020  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  3021  				Mode: networking.OutboundTrafficPolicy_REGISTRY_ONLY,
  3022  			},
  3023  		},
  3024  		{
  3025  			name:       "MeshConfig registry only, sidecar without OutboundTrafficPolicy",
  3026  			meshConfig: meshConfigWithRegistryOnly,
  3027  			sidecar:    configWithoutOutboundTrafficPolicy,
  3028  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  3029  				Mode: networking.OutboundTrafficPolicy_REGISTRY_ONLY,
  3030  			},
  3031  		},
  3032  		{
  3033  			name:       "MeshConfig registry only, Sidecar with registry only",
  3034  			meshConfig: meshConfigWithRegistryOnly,
  3035  			sidecar:    configRegistryOnly,
  3036  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  3037  				Mode: networking.OutboundTrafficPolicy_REGISTRY_ONLY,
  3038  			},
  3039  		},
  3040  		{
  3041  			name:       "MeshConfig registry only, Sidecar with allow any",
  3042  			meshConfig: meshConfigWithRegistryOnly,
  3043  			sidecar:    configAllowAny,
  3044  			outboundTrafficPolicy: &networking.OutboundTrafficPolicy{
  3045  				Mode: networking.OutboundTrafficPolicy_ALLOW_ANY,
  3046  			},
  3047  		},
  3048  	}
  3049  
  3050  	for i, test := range tests {
  3051  		t.Run(test.name, func(t *testing.T) {
  3052  			ps := NewPushContext()
  3053  			ps.Mesh = tests[i].meshConfig
  3054  
  3055  			var sidecarScope *SidecarScope
  3056  			if test.sidecar == nil {
  3057  				sidecarScope = DefaultSidecarScopeForNamespace(ps, "not-default")
  3058  			} else {
  3059  				sidecarScope = convertToSidecarScope(ps, test.sidecar, test.sidecar.Namespace)
  3060  			}
  3061  
  3062  			if !reflect.DeepEqual(test.outboundTrafficPolicy, sidecarScope.OutboundTrafficPolicy) {
  3063  				t.Errorf("Unexpected sidecar outbound traffic, want %v, found %v",
  3064  					test.outboundTrafficPolicy, sidecarScope.OutboundTrafficPolicy)
  3065  			}
  3066  		})
  3067  	}
  3068  }
  3069  
  3070  func TestInboundConnectionPoolForPort(t *testing.T) {
  3071  	connectionPoolSettings := &networking.ConnectionPoolSettings{
  3072  		Http: &networking.ConnectionPoolSettings_HTTPSettings{
  3073  			Http1MaxPendingRequests:  1024,
  3074  			Http2MaxRequests:         1024,
  3075  			MaxRequestsPerConnection: 1024,
  3076  			MaxRetries:               1024,
  3077  			IdleTimeout:              durationpb.New(5 * time.Second),
  3078  			H2UpgradePolicy:          networking.ConnectionPoolSettings_HTTPSettings_UPGRADE,
  3079  		},
  3080  		Tcp: &networking.ConnectionPoolSettings_TCPSettings{
  3081  			MaxConnections: 1024,
  3082  			ConnectTimeout: durationpb.New(6 * time.Second),
  3083  			TcpKeepalive: &networking.ConnectionPoolSettings_TCPSettings_TcpKeepalive{
  3084  				Probes:   3,
  3085  				Time:     durationpb.New(7 * time.Second),
  3086  				Interval: durationpb.New(8 * time.Second),
  3087  			},
  3088  			MaxConnectionDuration: durationpb.New(9 * time.Second),
  3089  		},
  3090  	}
  3091  
  3092  	overrideConnectionPool := &networking.ConnectionPoolSettings{
  3093  		Http: &networking.ConnectionPoolSettings_HTTPSettings{
  3094  			Http1MaxPendingRequests:  1,
  3095  			Http2MaxRequests:         2,
  3096  			MaxRequestsPerConnection: 3,
  3097  			MaxRetries:               4,
  3098  			IdleTimeout:              durationpb.New(1 * time.Second),
  3099  			H2UpgradePolicy:          networking.ConnectionPoolSettings_HTTPSettings_DO_NOT_UPGRADE,
  3100  		},
  3101  	}
  3102  
  3103  	tests := map[string]struct {
  3104  		sidecar *networking.Sidecar
  3105  		// port to settings map
  3106  		want map[int]*networking.ConnectionPoolSettings
  3107  	}{
  3108  		"no settings": {
  3109  			sidecar: &networking.Sidecar{},
  3110  			want: map[int]*networking.ConnectionPoolSettings{
  3111  				22:  nil,
  3112  				80:  nil,
  3113  				443: nil,
  3114  			},
  3115  		},
  3116  		"no settings multiple ports": {
  3117  			sidecar: &networking.Sidecar{
  3118  				Ingress: []*networking.IstioIngressListener{
  3119  					{
  3120  						Port: &networking.SidecarPort{
  3121  							Number:   80,
  3122  							Protocol: "HTTP",
  3123  							Name:     "http",
  3124  						},
  3125  					},
  3126  					{
  3127  						Port: &networking.SidecarPort{
  3128  							Number:   443,
  3129  							Protocol: "HTTPS",
  3130  							Name:     "https",
  3131  						},
  3132  					},
  3133  				},
  3134  			},
  3135  			want: map[int]*networking.ConnectionPoolSettings{
  3136  				22:  nil,
  3137  				80:  nil,
  3138  				443: nil,
  3139  			},
  3140  		},
  3141  		"single port with settings": {
  3142  			sidecar: &networking.Sidecar{
  3143  				Ingress: []*networking.IstioIngressListener{
  3144  					{
  3145  						Port: &networking.SidecarPort{
  3146  							Number:   80,
  3147  							Protocol: "HTTP",
  3148  							Name:     "http",
  3149  						},
  3150  						ConnectionPool: connectionPoolSettings,
  3151  					},
  3152  				},
  3153  			},
  3154  			want: map[int]*networking.ConnectionPoolSettings{
  3155  				22:  nil,
  3156  				80:  connectionPoolSettings,
  3157  				443: nil,
  3158  			},
  3159  		},
  3160  		"top level settings": {
  3161  			sidecar: &networking.Sidecar{
  3162  				InboundConnectionPool: connectionPoolSettings,
  3163  				Ingress: []*networking.IstioIngressListener{
  3164  					{
  3165  						Port: &networking.SidecarPort{
  3166  							Number:   80,
  3167  							Protocol: "HTTP",
  3168  							Name:     "http",
  3169  						},
  3170  					},
  3171  				},
  3172  			},
  3173  			want: map[int]*networking.ConnectionPoolSettings{
  3174  				// with a default setting on the sidecar, we'll return it for any port we're asked about
  3175  				22:  connectionPoolSettings,
  3176  				80:  connectionPoolSettings,
  3177  				443: connectionPoolSettings,
  3178  			},
  3179  		},
  3180  		"port settings override top level": {
  3181  			sidecar: &networking.Sidecar{
  3182  				InboundConnectionPool: connectionPoolSettings,
  3183  				Ingress: []*networking.IstioIngressListener{
  3184  					{
  3185  						Port: &networking.SidecarPort{
  3186  							Number:   80,
  3187  							Protocol: "HTTP",
  3188  							Name:     "http",
  3189  						},
  3190  						ConnectionPool: overrideConnectionPool,
  3191  					},
  3192  				},
  3193  			},
  3194  			want: map[int]*networking.ConnectionPoolSettings{
  3195  				// with a default setting on the sidecar, we'll return it for any port we're asked about
  3196  				22:  connectionPoolSettings,
  3197  				80:  overrideConnectionPool,
  3198  				443: connectionPoolSettings,
  3199  			},
  3200  		},
  3201  	}
  3202  	for name, tt := range tests {
  3203  		t.Run(name, func(t *testing.T) {
  3204  			ps := NewPushContext()
  3205  			ps.Mesh = mesh.DefaultMeshConfig()
  3206  
  3207  			sidecar := &config.Config{
  3208  				Meta: config.Meta{
  3209  					GroupVersionKind: gvk.Sidecar,
  3210  					Name:             "sidecar",
  3211  					Namespace:        strings.Replace(name, " ", "-", -1),
  3212  				},
  3213  				Spec: tt.sidecar,
  3214  			}
  3215  			scope := convertToSidecarScope(ps, sidecar, sidecar.Namespace)
  3216  
  3217  			for port, expected := range tt.want {
  3218  				actual := scope.InboundConnectionPoolForPort(port)
  3219  				if !reflect.DeepEqual(actual, expected) {
  3220  					t.Errorf("for port %d, wanted %#v but got: %#v", port, expected, actual)
  3221  				}
  3222  			}
  3223  		})
  3224  	}
  3225  }
  3226  
  3227  func BenchmarkConvertIstioListenerToWrapper(b *testing.B) {
  3228  	b.Run("small-exact", func(b *testing.B) {
  3229  		benchmarkConvertIstioListenerToWrapper(b, 10, 3, "", false)
  3230  	})
  3231  	b.Run("small-wildcard", func(b *testing.B) {
  3232  		benchmarkConvertIstioListenerToWrapper(b, 10, 3, "*.", false)
  3233  	})
  3234  	b.Run("small-match-all", func(b *testing.B) {
  3235  		benchmarkConvertIstioListenerToWrapper(b, 10, 3, "", true)
  3236  	})
  3237  
  3238  	b.Run("middle-exact", func(b *testing.B) {
  3239  		benchmarkConvertIstioListenerToWrapper(b, 100, 10, "", false)
  3240  	})
  3241  	b.Run("middle-wildcard", func(b *testing.B) {
  3242  		benchmarkConvertIstioListenerToWrapper(b, 100, 10, "*.", false)
  3243  	})
  3244  	b.Run("middle-match-all", func(b *testing.B) {
  3245  		benchmarkConvertIstioListenerToWrapper(b, 100, 10, "", true)
  3246  	})
  3247  
  3248  	b.Run("big-exact", func(b *testing.B) {
  3249  		benchmarkConvertIstioListenerToWrapper(b, 300, 15, "", false)
  3250  	})
  3251  	b.Run("big-wildcard", func(b *testing.B) {
  3252  		benchmarkConvertIstioListenerToWrapper(b, 300, 15, "*.", false)
  3253  	})
  3254  	b.Run("big-match-all", func(b *testing.B) {
  3255  		benchmarkConvertIstioListenerToWrapper(b, 300, 15, "", true)
  3256  	})
  3257  }
  3258  
  3259  func benchmarkConvertIstioListenerToWrapper(b *testing.B, vsNum int, hostNum int, wildcard string, matchAll bool) {
  3260  	// virtual service
  3261  	cfgs := make([]config.Config, 0)
  3262  	for i := 0; i < vsNum; i++ {
  3263  		cfgs = append(cfgs, config.Config{
  3264  			Meta: config.Meta{
  3265  				GroupVersionKind: gvk.VirtualService,
  3266  				Name:             "vs-name-" + strconv.Itoa(i),
  3267  				Namespace:        "default",
  3268  			},
  3269  			Spec: &networking.VirtualService{
  3270  				Hosts: []string{"host-" + strconv.Itoa(i) + ".com"},
  3271  			},
  3272  		})
  3273  	}
  3274  	ps := NewPushContext()
  3275  	ps.virtualServiceIndex.publicByGateway[constants.IstioMeshGateway] = cfgs
  3276  
  3277  	// service
  3278  	svcList := make([]*Service, 0, vsNum)
  3279  	for i := 0; i < vsNum; i++ {
  3280  		svcList = append(svcList, &Service{
  3281  			Attributes: ServiceAttributes{Namespace: "default"},
  3282  			Hostname:   host.Name("host-" + strconv.Itoa(i) + ".com"),
  3283  		})
  3284  	}
  3285  	ps.ServiceIndex.public = svcList
  3286  
  3287  	hosts := make([]string, 0)
  3288  	if matchAll {
  3289  		// default/*
  3290  		hosts = append(hosts, "default/*")
  3291  	} else {
  3292  		// default/xx or default/*.xx
  3293  		for i := 0; i < hostNum; i++ {
  3294  			h := "default/" + wildcard + "host-" + strconv.Itoa(i) + ".com"
  3295  			hosts = append(hosts, h)
  3296  		}
  3297  	}
  3298  
  3299  	istioListener := &networking.IstioEgressListener{
  3300  		Hosts: hosts,
  3301  	}
  3302  
  3303  	b.ResetTimer()
  3304  	for i := 0; i < b.N; i++ {
  3305  		convertIstioListenerToWrapper(ps, "default", istioListener)
  3306  	}
  3307  }
  3308  
  3309  func TestComputeWildcardHostVirtualServiceIndex(t *testing.T) {
  3310  	oldestTime := time.Now().Add(-2 * time.Hour)
  3311  	olderTime := time.Now().Add(-1 * time.Hour)
  3312  	newerTime := time.Now()
  3313  	virtualServices := []config.Config{
  3314  		{
  3315  			Meta: config.Meta{
  3316  				Name:              "foo",
  3317  				Namespace:         "default",
  3318  				CreationTimestamp: newerTime,
  3319  			},
  3320  			Spec: &networking.VirtualService{
  3321  				Hosts: []string{"foo.example.com"},
  3322  			},
  3323  		},
  3324  		{
  3325  			Meta: config.Meta{
  3326  				Name:              "foo2",
  3327  				Namespace:         "default",
  3328  				CreationTimestamp: olderTime.Add(30 * time.Minute), // This should not be used despite being older than foo
  3329  			},
  3330  			Spec: &networking.VirtualService{
  3331  				Hosts: []string{"foo.example.com"},
  3332  			},
  3333  		},
  3334  		{
  3335  			Meta: config.Meta{
  3336  				Name:              "wild",
  3337  				Namespace:         "default",
  3338  				CreationTimestamp: olderTime,
  3339  			},
  3340  			Spec: &networking.VirtualService{
  3341  				Hosts: []string{"*.example.com"},
  3342  			},
  3343  		},
  3344  		{
  3345  			Meta: config.Meta{
  3346  				Name:              "barwild",
  3347  				Namespace:         "default",
  3348  				CreationTimestamp: oldestTime,
  3349  			},
  3350  			Spec: &networking.VirtualService{
  3351  				Hosts: []string{"*.bar.example.com"},
  3352  			},
  3353  		},
  3354  		{
  3355  			Meta: config.Meta{
  3356  				Name:              "barwild2",
  3357  				Namespace:         "default",
  3358  				CreationTimestamp: olderTime,
  3359  			},
  3360  			Spec: &networking.VirtualService{
  3361  				Hosts: []string{"*.bar.example.com"},
  3362  			},
  3363  		},
  3364  	}
  3365  
  3366  	services := []*Service{
  3367  		{
  3368  			Hostname: "foo.example.com",
  3369  		},
  3370  		{
  3371  			Hostname: "baz.example.com",
  3372  		},
  3373  		{
  3374  			Hostname: "qux.bar.example.com",
  3375  		},
  3376  		{
  3377  			Hostname: "*.bar.example.com",
  3378  		},
  3379  	}
  3380  
  3381  	tests := []struct {
  3382  		name            string
  3383  		virtualServices []config.Config
  3384  		services        []*Service
  3385  		expectedIndex   map[host.Name]types.NamespacedName
  3386  		oldestWins      bool
  3387  	}{
  3388  		{
  3389  			name:            "most specific",
  3390  			virtualServices: virtualServices,
  3391  			services:        services,
  3392  			expectedIndex: map[host.Name]types.NamespacedName{
  3393  				"foo.example.com":     {Name: "foo", Namespace: "default"},
  3394  				"baz.example.com":     {Name: "wild", Namespace: "default"},
  3395  				"qux.bar.example.com": {Name: "barwild", Namespace: "default"},
  3396  				"*.bar.example.com":   {Name: "barwild", Namespace: "default"},
  3397  			},
  3398  		},
  3399  		{
  3400  			name:            "oldest wins",
  3401  			virtualServices: virtualServices,
  3402  			services:        services,
  3403  			expectedIndex: map[host.Name]types.NamespacedName{
  3404  				"foo.example.com":     {Name: "wild", Namespace: "default"},
  3405  				"baz.example.com":     {Name: "wild", Namespace: "default"},
  3406  				"qux.bar.example.com": {Name: "barwild", Namespace: "default"},
  3407  				"*.bar.example.com":   {Name: "barwild", Namespace: "default"},
  3408  			},
  3409  			oldestWins: true,
  3410  		},
  3411  	}
  3412  
  3413  	for _, tt := range tests {
  3414  		t.Run(tt.name, func(t *testing.T) {
  3415  			if tt.oldestWins {
  3416  				test.SetForTest(t, &features.PersistOldestWinsHeuristicForVirtualServiceHostMatching, true)
  3417  			}
  3418  			index := computeWildcardHostVirtualServiceIndex(tt.virtualServices, tt.services)
  3419  			if !reflect.DeepEqual(tt.expectedIndex, index) {
  3420  				t.Errorf("Expected index %v, got %v", tt.expectedIndex, index)
  3421  			}
  3422  		})
  3423  	}
  3424  }