github.com/cilium/cilium@v1.16.2/operator/pkg/model/ingestion/ingress_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package ingestion
     5  
     6  import (
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	networkingv1 "k8s.io/api/networking/v1"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  
    14  	"github.com/cilium/cilium/operator/pkg/model"
    15  )
    16  
    17  var exactPathType = networkingv1.PathTypeExact
    18  
    19  var prefixPathType = networkingv1.PathTypePrefix
    20  
    21  var implementationSpecificPathType = networkingv1.PathTypeImplementationSpecific
    22  
    23  var testAnnotations = map[string]string{
    24  	"service.beta.kubernetes.io/dummy-load-balancer-backend-protocol":    "http",
    25  	"service.beta.kubernetes.io/dummy-load-balancer-access-log-enabled":  "true",
    26  	"service.alpha.kubernetes.io/dummy-load-balancer-access-log-enabled": "true",
    27  }
    28  
    29  var defaultSecretNamespace = "default-secret-namespace"
    30  
    31  var defaultSecretName = "default-secret-name"
    32  
    33  // Add the ingress objects in
    34  // https://github.com/kubernetes-sigs/ingress-controller-conformance/tree/master/features
    35  // as test fixtures
    36  
    37  // default timeout for the ingress conformance tests
    38  var listenerDefaultTimeout = model.Timeout{
    39  	Request: nil,
    40  }
    41  
    42  // Just a default backend should produce one simple listener.
    43  var defaultBackend = networkingv1.Ingress{
    44  	ObjectMeta: metav1.ObjectMeta{
    45  		Name:      "load-balancing",
    46  		Namespace: "random-namespace",
    47  	},
    48  	Spec: networkingv1.IngressSpec{
    49  		IngressClassName: stringp("cilium"),
    50  		DefaultBackend: &networkingv1.IngressBackend{
    51  			Service: &networkingv1.IngressServiceBackend{
    52  				Name: "default-backend",
    53  				Port: networkingv1.ServiceBackendPort{
    54  					Number: 8080,
    55  				},
    56  			},
    57  		},
    58  	},
    59  }
    60  
    61  var defaultBackendLegacy = networkingv1.Ingress{
    62  	ObjectMeta: metav1.ObjectMeta{
    63  		Name:        "load-balancing",
    64  		Namespace:   "random-namespace",
    65  		Annotations: map[string]string{"kubernetes.io/ingress.class": "cilium"},
    66  	},
    67  	Spec: networkingv1.IngressSpec{
    68  		DefaultBackend: &networkingv1.IngressBackend{
    69  			Service: &networkingv1.IngressServiceBackend{
    70  				Name: "default-backend",
    71  				Port: networkingv1.ServiceBackendPort{
    72  					Number: 8080,
    73  				},
    74  			},
    75  		},
    76  	},
    77  }
    78  
    79  var defaultBackendLegacyOverride = networkingv1.Ingress{
    80  	ObjectMeta: metav1.ObjectMeta{
    81  		Name:        "load-balancing",
    82  		Namespace:   "random-namespace",
    83  		Annotations: map[string]string{"kubernetes.io/ingress.class": "cilium"},
    84  	},
    85  	Spec: networkingv1.IngressSpec{
    86  		IngressClassName: stringp("contour"),
    87  		DefaultBackend: &networkingv1.IngressBackend{
    88  			Service: &networkingv1.IngressServiceBackend{
    89  				Name: "default-backend",
    90  				Port: networkingv1.ServiceBackendPort{
    91  					Number: 8080,
    92  				},
    93  			},
    94  		},
    95  	},
    96  }
    97  
    98  var defaultBackendListeners = []model.HTTPListener{
    99  	{
   100  		Sources: []model.FullyQualifiedResource{
   101  			{
   102  				Name:      "load-balancing",
   103  				Namespace: "random-namespace",
   104  				Version:   "v1",
   105  				Kind:      "Ingress",
   106  			},
   107  		},
   108  		Port:     80,
   109  		Hostname: "*",
   110  		Routes: []model.HTTPRoute{
   111  			{
   112  				Backends: []model.Backend{
   113  					{
   114  						Name:      "default-backend",
   115  						Namespace: "random-namespace",
   116  						Port: &model.BackendPort{
   117  							Port: 8080,
   118  						},
   119  					},
   120  				},
   121  				Timeout: listenerDefaultTimeout,
   122  			},
   123  		},
   124  	},
   125  }
   126  
   127  var defaultBackendListenersWithRequestTimeout = []model.HTTPListener{
   128  	{
   129  		Sources: []model.FullyQualifiedResource{
   130  			{
   131  				Name:      "load-balancing",
   132  				Namespace: "random-namespace",
   133  				Version:   "v1",
   134  				Kind:      "Ingress",
   135  			},
   136  		},
   137  		Port:     80,
   138  		Hostname: "*",
   139  		Routes: []model.HTTPRoute{
   140  			{
   141  				Backends: []model.Backend{
   142  					{
   143  						Name:      "default-backend",
   144  						Namespace: "random-namespace",
   145  						Port: &model.BackendPort{
   146  							Port: 8080,
   147  						},
   148  					},
   149  				},
   150  				Timeout: model.Timeout{
   151  					Request: model.AddressOf(time.Second * 10),
   152  				},
   153  			},
   154  		},
   155  	},
   156  }
   157  
   158  // Ingress Conformance test resources
   159  
   160  // The hostRules resource from the ingress conformance test should produce
   161  // three listeners, one for host with no TLS config, then one insecure and one
   162  // secure for the host with TLS config.
   163  var hostRules = networkingv1.Ingress{
   164  	ObjectMeta: metav1.ObjectMeta{
   165  		Name:      "host-rules",
   166  		Namespace: "random-namespace",
   167  	},
   168  	Spec: networkingv1.IngressSpec{
   169  		TLS: []networkingv1.IngressTLS{
   170  			{
   171  				Hosts:      []string{"foo.bar.com"},
   172  				SecretName: "conformance-tls",
   173  			},
   174  		},
   175  		Rules: []networkingv1.IngressRule{
   176  			{
   177  				Host: "*.foo.com",
   178  				IngressRuleValue: networkingv1.IngressRuleValue{
   179  					HTTP: &networkingv1.HTTPIngressRuleValue{
   180  						Paths: []networkingv1.HTTPIngressPath{
   181  							{
   182  								Path: "/",
   183  								Backend: networkingv1.IngressBackend{
   184  									Service: &networkingv1.IngressServiceBackend{
   185  										Name: "wildcard-foo-com",
   186  										Port: networkingv1.ServiceBackendPort{
   187  											Number: 8080,
   188  										},
   189  									},
   190  								},
   191  								PathType: &prefixPathType,
   192  							},
   193  						},
   194  					},
   195  				},
   196  			},
   197  			{
   198  				Host: "foo.bar.com",
   199  				IngressRuleValue: networkingv1.IngressRuleValue{
   200  					HTTP: &networkingv1.HTTPIngressRuleValue{
   201  						Paths: []networkingv1.HTTPIngressPath{
   202  							{
   203  								Path: "/",
   204  								Backend: networkingv1.IngressBackend{
   205  									Service: &networkingv1.IngressServiceBackend{
   206  										Name: "foo-bar-com",
   207  										Port: networkingv1.ServiceBackendPort{
   208  											Name: "http",
   209  										},
   210  									},
   211  								},
   212  								PathType: &prefixPathType,
   213  							},
   214  						},
   215  					},
   216  				},
   217  			},
   218  		},
   219  	},
   220  }
   221  
   222  var hostRulesListeners = []model.HTTPListener{
   223  	{
   224  		Name: "ing-host-rules-random-namespace-*.foo.com",
   225  		Sources: []model.FullyQualifiedResource{
   226  			{
   227  				Name:      "host-rules",
   228  				Namespace: "random-namespace",
   229  				Version:   "v1",
   230  				Kind:      "Ingress",
   231  			},
   232  		},
   233  		Port:     80,
   234  		Hostname: "*.foo.com",
   235  		Routes: []model.HTTPRoute{
   236  			{
   237  				PathMatch: model.StringMatch{
   238  					Prefix: "/",
   239  				},
   240  				Backends: []model.Backend{
   241  					{
   242  						Name:      "wildcard-foo-com",
   243  						Namespace: "random-namespace",
   244  						Port: &model.BackendPort{
   245  							Port: 8080,
   246  						},
   247  					},
   248  				},
   249  				Timeout: listenerDefaultTimeout,
   250  			},
   251  		},
   252  	},
   253  	{
   254  		Name: "ing-host-rules-random-namespace-foo.bar.com",
   255  		Sources: []model.FullyQualifiedResource{
   256  			{
   257  				Name:      "host-rules",
   258  				Namespace: "random-namespace",
   259  				Version:   "v1",
   260  				Kind:      "Ingress",
   261  			},
   262  		},
   263  		Port:     80,
   264  		Hostname: "foo.bar.com",
   265  		Routes: []model.HTTPRoute{
   266  			{
   267  				PathMatch: model.StringMatch{
   268  					Prefix: "/",
   269  				},
   270  				Backends: []model.Backend{
   271  					{
   272  						Name:      "foo-bar-com",
   273  						Namespace: "random-namespace",
   274  						Port: &model.BackendPort{
   275  							Name: "http",
   276  						},
   277  					},
   278  				},
   279  				Timeout: listenerDefaultTimeout,
   280  			},
   281  		},
   282  	},
   283  	{
   284  		Name: "ing-host-rules-random-namespace-foo.bar.com",
   285  		Sources: []model.FullyQualifiedResource{
   286  			{
   287  				Name:      "host-rules",
   288  				Namespace: "random-namespace",
   289  				Version:   "v1",
   290  				Kind:      "Ingress",
   291  			},
   292  		},
   293  		Port:     443,
   294  		Hostname: "foo.bar.com",
   295  		TLS: []model.TLSSecret{
   296  			{
   297  				Name:      "conformance-tls",
   298  				Namespace: "random-namespace",
   299  			},
   300  		},
   301  		Routes: []model.HTTPRoute{
   302  			{
   303  				PathMatch: model.StringMatch{
   304  					Prefix: "/",
   305  				},
   306  				Backends: []model.Backend{
   307  					{
   308  						Name:      "foo-bar-com",
   309  						Namespace: "random-namespace",
   310  						Port: &model.BackendPort{
   311  							Name: "http",
   312  						},
   313  					},
   314  				},
   315  				Timeout: listenerDefaultTimeout,
   316  			},
   317  		},
   318  	},
   319  }
   320  
   321  // The pathRules resource should produce four listeners, one for each host
   322  // used in the Ingress.
   323  
   324  var pathRules = networkingv1.Ingress{
   325  	ObjectMeta: metav1.ObjectMeta{
   326  		Name:      "path-rules",
   327  		Namespace: "random-namespace",
   328  	},
   329  	Spec: networkingv1.IngressSpec{
   330  		Rules: []networkingv1.IngressRule{
   331  			{
   332  				Host: "exact-path-rules",
   333  				IngressRuleValue: networkingv1.IngressRuleValue{
   334  					HTTP: &networkingv1.HTTPIngressRuleValue{
   335  						Paths: []networkingv1.HTTPIngressPath{
   336  							{
   337  								Path: "/foo",
   338  								Backend: networkingv1.IngressBackend{
   339  									Service: &networkingv1.IngressServiceBackend{
   340  										Name: "foo-exact",
   341  										Port: networkingv1.ServiceBackendPort{
   342  											Number: 8080,
   343  										},
   344  									},
   345  								},
   346  								PathType: &exactPathType,
   347  							},
   348  						},
   349  					},
   350  				},
   351  			},
   352  			{
   353  				Host: "prefix-path-rules",
   354  				IngressRuleValue: networkingv1.IngressRuleValue{
   355  					HTTP: &networkingv1.HTTPIngressRuleValue{
   356  						Paths: []networkingv1.HTTPIngressPath{
   357  							{
   358  								Path: "/foo",
   359  								Backend: networkingv1.IngressBackend{
   360  									Service: &networkingv1.IngressServiceBackend{
   361  										Name: "foo-prefix",
   362  										Port: networkingv1.ServiceBackendPort{
   363  											Number: 8080,
   364  										},
   365  									},
   366  								},
   367  								PathType: &prefixPathType,
   368  							},
   369  							{
   370  								Path: "/aaa/bbb",
   371  								Backend: networkingv1.IngressBackend{
   372  									Service: &networkingv1.IngressServiceBackend{
   373  										Name: "aaa-slash-bbb-prefix",
   374  										Port: networkingv1.ServiceBackendPort{
   375  											Number: 8080,
   376  										},
   377  									},
   378  								},
   379  								PathType: &prefixPathType,
   380  							},
   381  							{
   382  								Path: "/aaa",
   383  								Backend: networkingv1.IngressBackend{
   384  									Service: &networkingv1.IngressServiceBackend{
   385  										Name: "aaa-prefix",
   386  										Port: networkingv1.ServiceBackendPort{
   387  											Number: 8080,
   388  										},
   389  									},
   390  								},
   391  								PathType: &prefixPathType,
   392  							},
   393  						},
   394  					},
   395  				},
   396  			},
   397  			{
   398  				Host: "mixed-path-rules",
   399  				IngressRuleValue: networkingv1.IngressRuleValue{
   400  					HTTP: &networkingv1.HTTPIngressRuleValue{
   401  						Paths: []networkingv1.HTTPIngressPath{
   402  							{
   403  								Path: "/foo",
   404  								Backend: networkingv1.IngressBackend{
   405  									Service: &networkingv1.IngressServiceBackend{
   406  										Name: "foo-prefix",
   407  										Port: networkingv1.ServiceBackendPort{
   408  											Number: 8080,
   409  										},
   410  									},
   411  								},
   412  								PathType: &prefixPathType,
   413  							},
   414  							{
   415  								Path: "/foo",
   416  								Backend: networkingv1.IngressBackend{
   417  									Service: &networkingv1.IngressServiceBackend{
   418  										Name: "foo-exact",
   419  										Port: networkingv1.ServiceBackendPort{
   420  											Number: 8080,
   421  										},
   422  									},
   423  								},
   424  								PathType: &exactPathType,
   425  							},
   426  						},
   427  					},
   428  				},
   429  			},
   430  			{
   431  				Host: "trailing-slash-path-rules",
   432  				IngressRuleValue: networkingv1.IngressRuleValue{
   433  					HTTP: &networkingv1.HTTPIngressRuleValue{
   434  						Paths: []networkingv1.HTTPIngressPath{
   435  							{
   436  								Path: "/aaa/bbb/",
   437  								Backend: networkingv1.IngressBackend{
   438  									Service: &networkingv1.IngressServiceBackend{
   439  										Name: "aaa-slash-bbb-slash-prefix",
   440  										Port: networkingv1.ServiceBackendPort{
   441  											Number: 8080,
   442  										},
   443  									},
   444  								},
   445  								PathType: &prefixPathType,
   446  							},
   447  							{
   448  								Path: "/foo/",
   449  								Backend: networkingv1.IngressBackend{
   450  									Service: &networkingv1.IngressServiceBackend{
   451  										Name: "foo-slash-exact",
   452  										Port: networkingv1.ServiceBackendPort{
   453  											Number: 8080,
   454  										},
   455  									},
   456  								},
   457  								PathType: &exactPathType,
   458  							},
   459  						},
   460  					},
   461  				},
   462  			},
   463  		},
   464  	},
   465  }
   466  
   467  var pathRulesListeners = []model.HTTPListener{
   468  	{
   469  		Name: "ing-path-rules-random-namespace-exact-path-rules",
   470  		Sources: []model.FullyQualifiedResource{
   471  			{
   472  				Name:      "path-rules",
   473  				Namespace: "random-namespace",
   474  				Version:   "v1",
   475  				Kind:      "Ingress",
   476  			},
   477  		},
   478  		Port:     80,
   479  		Hostname: "exact-path-rules",
   480  		Routes: []model.HTTPRoute{
   481  			{
   482  				PathMatch: model.StringMatch{
   483  					Exact: "/foo",
   484  				},
   485  				Backends: []model.Backend{
   486  					{
   487  						Name:      "foo-exact",
   488  						Namespace: "random-namespace",
   489  						Port: &model.BackendPort{
   490  							Port: 8080,
   491  						},
   492  					},
   493  				},
   494  				Timeout: listenerDefaultTimeout,
   495  			},
   496  		},
   497  	},
   498  	{
   499  		Name: "ing-path-rules-random-namespace-mixed-path-rules",
   500  		Sources: []model.FullyQualifiedResource{
   501  			{
   502  				Name:      "path-rules",
   503  				Namespace: "random-namespace",
   504  				Version:   "v1",
   505  				Kind:      "Ingress",
   506  			},
   507  		},
   508  		Port:     80,
   509  		Hostname: "mixed-path-rules",
   510  		Routes: []model.HTTPRoute{
   511  			{
   512  				PathMatch: model.StringMatch{
   513  					Prefix: "/foo",
   514  				},
   515  				Backends: []model.Backend{
   516  					{
   517  						Name:      "foo-prefix",
   518  						Namespace: "random-namespace",
   519  						Port: &model.BackendPort{
   520  							Port: 8080,
   521  						},
   522  					},
   523  				},
   524  				Timeout: listenerDefaultTimeout,
   525  			},
   526  			{
   527  				PathMatch: model.StringMatch{
   528  					Exact: "/foo",
   529  				},
   530  				Backends: []model.Backend{
   531  					{
   532  						Name:      "foo-exact",
   533  						Namespace: "random-namespace",
   534  						Port: &model.BackendPort{
   535  							Port: 8080,
   536  						},
   537  					},
   538  				},
   539  				Timeout: listenerDefaultTimeout,
   540  			},
   541  		},
   542  	},
   543  	{
   544  		Name: "ing-path-rules-random-namespace-prefix-path-rules",
   545  		Sources: []model.FullyQualifiedResource{
   546  			{
   547  				Name:      "path-rules",
   548  				Namespace: "random-namespace",
   549  				Version:   "v1",
   550  				Kind:      "Ingress",
   551  			},
   552  		},
   553  		Port:     80,
   554  		Hostname: "prefix-path-rules",
   555  		Routes: []model.HTTPRoute{
   556  			{
   557  				PathMatch: model.StringMatch{
   558  					Prefix: "/foo",
   559  				},
   560  				Backends: []model.Backend{
   561  					{
   562  						Name:      "foo-prefix",
   563  						Namespace: "random-namespace",
   564  						Port: &model.BackendPort{
   565  							Port: 8080,
   566  						},
   567  					},
   568  				},
   569  				Timeout: listenerDefaultTimeout,
   570  			},
   571  			{
   572  				PathMatch: model.StringMatch{
   573  					Prefix: "/aaa/bbb",
   574  				},
   575  				Backends: []model.Backend{
   576  					{
   577  						Name:      "aaa-slash-bbb-prefix",
   578  						Namespace: "random-namespace",
   579  						Port: &model.BackendPort{
   580  							Port: 8080,
   581  						},
   582  					},
   583  				},
   584  				Timeout: listenerDefaultTimeout,
   585  			},
   586  			{
   587  				PathMatch: model.StringMatch{
   588  					Prefix: "/aaa",
   589  				},
   590  				Backends: []model.Backend{
   591  					{
   592  						Name:      "aaa-prefix",
   593  						Namespace: "random-namespace",
   594  						Port: &model.BackendPort{
   595  							Port: 8080,
   596  						},
   597  					},
   598  				},
   599  				Timeout: listenerDefaultTimeout,
   600  			},
   601  		},
   602  	},
   603  	{
   604  		Name: "ing-path-rules-random-namespace-trailing-slash-path-rules",
   605  		Sources: []model.FullyQualifiedResource{
   606  			{
   607  				Name:      "path-rules",
   608  				Namespace: "random-namespace",
   609  				Version:   "v1",
   610  				Kind:      "Ingress",
   611  			},
   612  		},
   613  		Port:     80,
   614  		Hostname: "trailing-slash-path-rules",
   615  		Routes: []model.HTTPRoute{
   616  			{
   617  				PathMatch: model.StringMatch{
   618  					Prefix: "/aaa/bbb/",
   619  				},
   620  				Backends: []model.Backend{
   621  					{
   622  						Name:      "aaa-slash-bbb-slash-prefix",
   623  						Namespace: "random-namespace",
   624  						Port: &model.BackendPort{
   625  							Port: 8080,
   626  						},
   627  					},
   628  				},
   629  				Timeout: listenerDefaultTimeout,
   630  			},
   631  			{
   632  				PathMatch: model.StringMatch{
   633  					Exact: "/foo/",
   634  				},
   635  				Backends: []model.Backend{
   636  					{
   637  						Name:      "foo-slash-exact",
   638  						Namespace: "random-namespace",
   639  						Port: &model.BackendPort{
   640  							Port: 8080,
   641  						},
   642  					},
   643  				},
   644  				Timeout: listenerDefaultTimeout,
   645  			},
   646  		},
   647  	},
   648  }
   649  
   650  // The complexIngress resource from the operator/pkg/ingress testsuite should
   651  // produce three Listeners with identical routes, for the default host `*`,
   652  // and then the two TLS hostnames.
   653  var complexIngress = networkingv1.Ingress{
   654  	ObjectMeta: metav1.ObjectMeta{
   655  		Name:        "dummy-ingress",
   656  		Namespace:   "dummy-namespace",
   657  		Annotations: testAnnotations,
   658  		Labels:      testAnnotations,
   659  		UID:         "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
   660  	},
   661  	Spec: networkingv1.IngressSpec{
   662  		IngressClassName: stringp("cilium"),
   663  		DefaultBackend: &networkingv1.IngressBackend{
   664  			Service: &networkingv1.IngressServiceBackend{
   665  				Name: "default-backend",
   666  				Port: networkingv1.ServiceBackendPort{
   667  					Number: 8080,
   668  				},
   669  			},
   670  		},
   671  		TLS: []networkingv1.IngressTLS{
   672  			{
   673  				Hosts:      []string{"very-secure.server.com"},
   674  				SecretName: "tls-very-secure-server-com",
   675  			},
   676  			{
   677  				Hosts: []string{
   678  					"another-very-secure.server.com",
   679  					"not-in-use.another-very-secure.server.com",
   680  				},
   681  				SecretName: "tls-another-very-secure-server-com",
   682  			},
   683  		},
   684  		Rules: []networkingv1.IngressRule{
   685  			{
   686  				IngressRuleValue: networkingv1.IngressRuleValue{
   687  					HTTP: &networkingv1.HTTPIngressRuleValue{
   688  						Paths: []networkingv1.HTTPIngressPath{
   689  							{
   690  								Path: "/dummy-path",
   691  								Backend: networkingv1.IngressBackend{
   692  									Service: &networkingv1.IngressServiceBackend{
   693  										Name: "dummy-backend",
   694  										Port: networkingv1.ServiceBackendPort{
   695  											Number: 8080,
   696  										},
   697  									},
   698  								},
   699  								PathType: &exactPathType,
   700  							},
   701  							{
   702  								Path: "/another-dummy-path",
   703  								Backend: networkingv1.IngressBackend{
   704  									Service: &networkingv1.IngressServiceBackend{
   705  										Name: "another-dummy-backend",
   706  										Port: networkingv1.ServiceBackendPort{
   707  											Number: 8081,
   708  										},
   709  									},
   710  								},
   711  								PathType: &prefixPathType,
   712  							},
   713  						},
   714  					},
   715  				},
   716  			},
   717  		},
   718  	},
   719  }
   720  
   721  var complexIngressListeners = []model.HTTPListener{
   722  	{
   723  		Sources: []model.FullyQualifiedResource{
   724  			{
   725  				Name:      "dummy-ingress",
   726  				Namespace: "dummy-namespace",
   727  				Version:   "v1",
   728  				Kind:      "Ingress",
   729  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
   730  			},
   731  		},
   732  		Port:     80,
   733  		Hostname: "*",
   734  		Routes: []model.HTTPRoute{
   735  			{
   736  				Backends: []model.Backend{
   737  					{
   738  						Name:      "default-backend",
   739  						Namespace: "dummy-namespace",
   740  						Port: &model.BackendPort{
   741  							Port: 8080,
   742  						},
   743  					},
   744  				},
   745  				Timeout: listenerDefaultTimeout,
   746  			},
   747  			{
   748  				PathMatch: model.StringMatch{
   749  					Exact: "/dummy-path",
   750  				},
   751  				Backends: []model.Backend{
   752  					{
   753  						Name:      "dummy-backend",
   754  						Namespace: "dummy-namespace",
   755  						Port: &model.BackendPort{
   756  							Port: 8080,
   757  						},
   758  					},
   759  				},
   760  				Timeout: listenerDefaultTimeout,
   761  			},
   762  			{
   763  				PathMatch: model.StringMatch{
   764  					Prefix: "/another-dummy-path",
   765  				},
   766  				Backends: []model.Backend{
   767  					{
   768  						Name:      "another-dummy-backend",
   769  						Namespace: "dummy-namespace",
   770  						Port: &model.BackendPort{
   771  							Port: 8081,
   772  						},
   773  					},
   774  				},
   775  				Timeout: listenerDefaultTimeout,
   776  			},
   777  		},
   778  	},
   779  	{
   780  		Sources: []model.FullyQualifiedResource{
   781  			{
   782  				Name:      "dummy-ingress",
   783  				Namespace: "dummy-namespace",
   784  				Version:   "v1",
   785  				Kind:      "Ingress",
   786  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
   787  			},
   788  		},
   789  		Port:     443,
   790  		Hostname: "another-very-secure.server.com",
   791  		TLS: []model.TLSSecret{
   792  			{
   793  				Name:      "tls-another-very-secure-server-com",
   794  				Namespace: "dummy-namespace",
   795  			},
   796  		},
   797  		Routes: []model.HTTPRoute{
   798  			{
   799  				Backends: []model.Backend{
   800  					{
   801  						Name:      "default-backend",
   802  						Namespace: "dummy-namespace",
   803  						Port: &model.BackendPort{
   804  							Port: 8080,
   805  						},
   806  					},
   807  				},
   808  				Timeout: listenerDefaultTimeout,
   809  			},
   810  			{
   811  				PathMatch: model.StringMatch{
   812  					Exact: "/dummy-path",
   813  				},
   814  				Backends: []model.Backend{
   815  					{
   816  						Name:      "dummy-backend",
   817  						Namespace: "dummy-namespace",
   818  						Port: &model.BackendPort{
   819  							Port: 8080,
   820  						},
   821  					},
   822  				},
   823  				Timeout: listenerDefaultTimeout,
   824  			},
   825  			{
   826  				PathMatch: model.StringMatch{
   827  					Prefix: "/another-dummy-path",
   828  				},
   829  				Backends: []model.Backend{
   830  					{
   831  						Name:      "another-dummy-backend",
   832  						Namespace: "dummy-namespace",
   833  						Port: &model.BackendPort{
   834  							Port: 8081,
   835  						},
   836  					},
   837  				},
   838  				Timeout: listenerDefaultTimeout,
   839  			},
   840  		},
   841  	},
   842  	{
   843  		Sources: []model.FullyQualifiedResource{
   844  			{
   845  				Name:      "dummy-ingress",
   846  				Namespace: "dummy-namespace",
   847  				Version:   "v1",
   848  				Kind:      "Ingress",
   849  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
   850  			},
   851  		},
   852  		Port:     443,
   853  		Hostname: "not-in-use.another-very-secure.server.com",
   854  		TLS: []model.TLSSecret{
   855  			{
   856  				Name:      "tls-another-very-secure-server-com",
   857  				Namespace: "dummy-namespace",
   858  			},
   859  		},
   860  		Routes: []model.HTTPRoute{
   861  			{
   862  				Backends: []model.Backend{
   863  					{
   864  						Name:      "default-backend",
   865  						Namespace: "dummy-namespace",
   866  						Port: &model.BackendPort{
   867  							Port: 8080,
   868  						},
   869  					},
   870  				},
   871  				Timeout: listenerDefaultTimeout,
   872  			},
   873  			{
   874  				PathMatch: model.StringMatch{
   875  					Exact: "/dummy-path",
   876  				},
   877  				Backends: []model.Backend{
   878  					{
   879  						Name:      "dummy-backend",
   880  						Namespace: "dummy-namespace",
   881  						Port: &model.BackendPort{
   882  							Port: 8080,
   883  						},
   884  					},
   885  				},
   886  				Timeout: listenerDefaultTimeout,
   887  			},
   888  			{
   889  				PathMatch: model.StringMatch{
   890  					Prefix: "/another-dummy-path",
   891  				},
   892  				Backends: []model.Backend{
   893  					{
   894  						Name:      "another-dummy-backend",
   895  						Namespace: "dummy-namespace",
   896  						Port: &model.BackendPort{
   897  							Port: 8081,
   898  						},
   899  					},
   900  				},
   901  				Timeout: listenerDefaultTimeout,
   902  			},
   903  		},
   904  	},
   905  	{
   906  		Sources: []model.FullyQualifiedResource{
   907  			{
   908  				Name:      "dummy-ingress",
   909  				Namespace: "dummy-namespace",
   910  				Version:   "v1",
   911  				Kind:      "Ingress",
   912  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
   913  			},
   914  		},
   915  		Port:     443,
   916  		Hostname: "very-secure.server.com",
   917  		TLS: []model.TLSSecret{
   918  			{
   919  				Name:      "tls-very-secure-server-com",
   920  				Namespace: "dummy-namespace",
   921  			},
   922  		},
   923  		Routes: []model.HTTPRoute{
   924  			{
   925  				Backends: []model.Backend{
   926  					{
   927  						Name:      "default-backend",
   928  						Namespace: "dummy-namespace",
   929  						Port: &model.BackendPort{
   930  							Port: 8080,
   931  						},
   932  					},
   933  				},
   934  				Timeout: listenerDefaultTimeout,
   935  			},
   936  			{
   937  				PathMatch: model.StringMatch{
   938  					Exact: "/dummy-path",
   939  				},
   940  				Backends: []model.Backend{
   941  					{
   942  						Name:      "dummy-backend",
   943  						Namespace: "dummy-namespace",
   944  						Port: &model.BackendPort{
   945  							Port: 8080,
   946  						},
   947  					},
   948  				},
   949  				Timeout: listenerDefaultTimeout,
   950  			},
   951  			{
   952  				PathMatch: model.StringMatch{
   953  					Prefix: "/another-dummy-path",
   954  				},
   955  				Backends: []model.Backend{
   956  					{
   957  						Name:      "another-dummy-backend",
   958  						Namespace: "dummy-namespace",
   959  						Port: &model.BackendPort{
   960  							Port: 8081,
   961  						},
   962  					},
   963  				},
   964  				Timeout: listenerDefaultTimeout,
   965  			},
   966  		},
   967  	},
   968  }
   969  
   970  // complexNodePortIngress is same as complexIngress but with NodePort service
   971  var complexNodePortIngress = networkingv1.Ingress{
   972  	ObjectMeta: metav1.ObjectMeta{
   973  		Name:      "dummy-ingress",
   974  		Namespace: "dummy-namespace",
   975  		Annotations: map[string]string{
   976  			"ingress.cilium.io/service-type":       "NodePort",
   977  			"ingress.cilium.io/insecure-node-port": "30000",
   978  			"ingress.cilium.io/secure-node-port":   "30001",
   979  		},
   980  		UID: "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
   981  	},
   982  	Spec: networkingv1.IngressSpec{
   983  		IngressClassName: stringp("cilium"),
   984  		DefaultBackend: &networkingv1.IngressBackend{
   985  			Service: &networkingv1.IngressServiceBackend{
   986  				Name: "default-backend",
   987  				Port: networkingv1.ServiceBackendPort{
   988  					Number: 8080,
   989  				},
   990  			},
   991  		},
   992  		TLS: []networkingv1.IngressTLS{
   993  			{
   994  				Hosts:      []string{"very-secure.server.com"},
   995  				SecretName: "tls-very-secure-server-com",
   996  			},
   997  			{
   998  				Hosts: []string{
   999  					"another-very-secure.server.com",
  1000  					"not-in-use.another-very-secure.server.com",
  1001  				},
  1002  				SecretName: "tls-another-very-secure-server-com",
  1003  			},
  1004  		},
  1005  		Rules: []networkingv1.IngressRule{
  1006  			{
  1007  				IngressRuleValue: networkingv1.IngressRuleValue{
  1008  					HTTP: &networkingv1.HTTPIngressRuleValue{
  1009  						Paths: []networkingv1.HTTPIngressPath{
  1010  							{
  1011  								Path: "/dummy-path",
  1012  								Backend: networkingv1.IngressBackend{
  1013  									Service: &networkingv1.IngressServiceBackend{
  1014  										Name: "dummy-backend",
  1015  										Port: networkingv1.ServiceBackendPort{
  1016  											Number: 8080,
  1017  										},
  1018  									},
  1019  								},
  1020  								PathType: &exactPathType,
  1021  							},
  1022  							{
  1023  								Path: "/another-dummy-path",
  1024  								Backend: networkingv1.IngressBackend{
  1025  									Service: &networkingv1.IngressServiceBackend{
  1026  										Name: "another-dummy-backend",
  1027  										Port: networkingv1.ServiceBackendPort{
  1028  											Number: 8081,
  1029  										},
  1030  									},
  1031  								},
  1032  								PathType: &prefixPathType,
  1033  							},
  1034  						},
  1035  					},
  1036  				},
  1037  			},
  1038  		},
  1039  	},
  1040  }
  1041  
  1042  var complexNodePortIngressListeners = []model.HTTPListener{
  1043  	{
  1044  		Sources: []model.FullyQualifiedResource{
  1045  			{
  1046  				Name:      "dummy-ingress",
  1047  				Namespace: "dummy-namespace",
  1048  				Version:   "v1",
  1049  				Kind:      "Ingress",
  1050  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
  1051  			},
  1052  		},
  1053  		Port:     80,
  1054  		Hostname: "*",
  1055  		Routes: []model.HTTPRoute{
  1056  			{
  1057  				Backends: []model.Backend{
  1058  					{
  1059  						Name:      "default-backend",
  1060  						Namespace: "dummy-namespace",
  1061  						Port: &model.BackendPort{
  1062  							Port: 8080,
  1063  						},
  1064  					},
  1065  				},
  1066  				Timeout: listenerDefaultTimeout,
  1067  			},
  1068  			{
  1069  				PathMatch: model.StringMatch{
  1070  					Exact: "/dummy-path",
  1071  				},
  1072  				Backends: []model.Backend{
  1073  					{
  1074  						Name:      "dummy-backend",
  1075  						Namespace: "dummy-namespace",
  1076  						Port: &model.BackendPort{
  1077  							Port: 8080,
  1078  						},
  1079  					},
  1080  				},
  1081  				Timeout: listenerDefaultTimeout,
  1082  			},
  1083  			{
  1084  				PathMatch: model.StringMatch{
  1085  					Prefix: "/another-dummy-path",
  1086  				},
  1087  				Backends: []model.Backend{
  1088  					{
  1089  						Name:      "another-dummy-backend",
  1090  						Namespace: "dummy-namespace",
  1091  						Port: &model.BackendPort{
  1092  							Port: 8081,
  1093  						},
  1094  					},
  1095  				},
  1096  				Timeout: listenerDefaultTimeout,
  1097  			},
  1098  		},
  1099  		Service: &model.Service{
  1100  			Type:             "NodePort",
  1101  			InsecureNodePort: uint32p(30000),
  1102  			SecureNodePort:   uint32p(30001),
  1103  		},
  1104  	},
  1105  	{
  1106  		Sources: []model.FullyQualifiedResource{
  1107  			{
  1108  				Name:      "dummy-ingress",
  1109  				Namespace: "dummy-namespace",
  1110  				Version:   "v1",
  1111  				Kind:      "Ingress",
  1112  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
  1113  			},
  1114  		},
  1115  		Port:     443,
  1116  		Hostname: "another-very-secure.server.com",
  1117  		TLS: []model.TLSSecret{
  1118  			{
  1119  				Name:      "tls-another-very-secure-server-com",
  1120  				Namespace: "dummy-namespace",
  1121  			},
  1122  		},
  1123  		Routes: []model.HTTPRoute{
  1124  			{
  1125  				Backends: []model.Backend{
  1126  					{
  1127  						Name:      "default-backend",
  1128  						Namespace: "dummy-namespace",
  1129  						Port: &model.BackendPort{
  1130  							Port: 8080,
  1131  						},
  1132  					},
  1133  				},
  1134  				Timeout: listenerDefaultTimeout,
  1135  			},
  1136  			{
  1137  				PathMatch: model.StringMatch{
  1138  					Exact: "/dummy-path",
  1139  				},
  1140  				Backends: []model.Backend{
  1141  					{
  1142  						Name:      "dummy-backend",
  1143  						Namespace: "dummy-namespace",
  1144  						Port: &model.BackendPort{
  1145  							Port: 8080,
  1146  						},
  1147  					},
  1148  				},
  1149  				Timeout: listenerDefaultTimeout,
  1150  			},
  1151  			{
  1152  				PathMatch: model.StringMatch{
  1153  					Prefix: "/another-dummy-path",
  1154  				},
  1155  				Backends: []model.Backend{
  1156  					{
  1157  						Name:      "another-dummy-backend",
  1158  						Namespace: "dummy-namespace",
  1159  						Port: &model.BackendPort{
  1160  							Port: 8081,
  1161  						},
  1162  					},
  1163  				},
  1164  				Timeout: listenerDefaultTimeout,
  1165  			},
  1166  		},
  1167  		Service: &model.Service{
  1168  			Type:             "NodePort",
  1169  			InsecureNodePort: uint32p(30000),
  1170  			SecureNodePort:   uint32p(30001),
  1171  		},
  1172  	},
  1173  	{
  1174  		Sources: []model.FullyQualifiedResource{
  1175  			{
  1176  				Name:      "dummy-ingress",
  1177  				Namespace: "dummy-namespace",
  1178  				Version:   "v1",
  1179  				Kind:      "Ingress",
  1180  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
  1181  			},
  1182  		},
  1183  		Port:     443,
  1184  		Hostname: "not-in-use.another-very-secure.server.com",
  1185  		TLS: []model.TLSSecret{
  1186  			{
  1187  				Name:      "tls-another-very-secure-server-com",
  1188  				Namespace: "dummy-namespace",
  1189  			},
  1190  		},
  1191  		Routes: []model.HTTPRoute{
  1192  			{
  1193  				Backends: []model.Backend{
  1194  					{
  1195  						Name:      "default-backend",
  1196  						Namespace: "dummy-namespace",
  1197  						Port: &model.BackendPort{
  1198  							Port: 8080,
  1199  						},
  1200  					},
  1201  				},
  1202  				Timeout: listenerDefaultTimeout,
  1203  			},
  1204  			{
  1205  				PathMatch: model.StringMatch{
  1206  					Exact: "/dummy-path",
  1207  				},
  1208  				Backends: []model.Backend{
  1209  					{
  1210  						Name:      "dummy-backend",
  1211  						Namespace: "dummy-namespace",
  1212  						Port: &model.BackendPort{
  1213  							Port: 8080,
  1214  						},
  1215  					},
  1216  				},
  1217  				Timeout: listenerDefaultTimeout,
  1218  			},
  1219  			{
  1220  				PathMatch: model.StringMatch{
  1221  					Prefix: "/another-dummy-path",
  1222  				},
  1223  				Backends: []model.Backend{
  1224  					{
  1225  						Name:      "another-dummy-backend",
  1226  						Namespace: "dummy-namespace",
  1227  						Port: &model.BackendPort{
  1228  							Port: 8081,
  1229  						},
  1230  					},
  1231  				},
  1232  				Timeout: listenerDefaultTimeout,
  1233  			},
  1234  		},
  1235  		Service: &model.Service{
  1236  			Type:             "NodePort",
  1237  			InsecureNodePort: uint32p(30000),
  1238  			SecureNodePort:   uint32p(30001),
  1239  		},
  1240  	},
  1241  	{
  1242  		Sources: []model.FullyQualifiedResource{
  1243  			{
  1244  				Name:      "dummy-ingress",
  1245  				Namespace: "dummy-namespace",
  1246  				Version:   "v1",
  1247  				Kind:      "Ingress",
  1248  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
  1249  			},
  1250  		},
  1251  		Port:     443,
  1252  		Hostname: "very-secure.server.com",
  1253  		TLS: []model.TLSSecret{
  1254  			{
  1255  				Name:      "tls-very-secure-server-com",
  1256  				Namespace: "dummy-namespace",
  1257  			},
  1258  		},
  1259  		Routes: []model.HTTPRoute{
  1260  			{
  1261  				Backends: []model.Backend{
  1262  					{
  1263  						Name:      "default-backend",
  1264  						Namespace: "dummy-namespace",
  1265  						Port: &model.BackendPort{
  1266  							Port: 8080,
  1267  						},
  1268  					},
  1269  				},
  1270  				Timeout: listenerDefaultTimeout,
  1271  			},
  1272  			{
  1273  				PathMatch: model.StringMatch{
  1274  					Exact: "/dummy-path",
  1275  				},
  1276  				Backends: []model.Backend{
  1277  					{
  1278  						Name:      "dummy-backend",
  1279  						Namespace: "dummy-namespace",
  1280  						Port: &model.BackendPort{
  1281  							Port: 8080,
  1282  						},
  1283  					},
  1284  				},
  1285  				Timeout: listenerDefaultTimeout,
  1286  			},
  1287  			{
  1288  				PathMatch: model.StringMatch{
  1289  					Prefix: "/another-dummy-path",
  1290  				},
  1291  				Backends: []model.Backend{
  1292  					{
  1293  						Name:      "another-dummy-backend",
  1294  						Namespace: "dummy-namespace",
  1295  						Port: &model.BackendPort{
  1296  							Port: 8081,
  1297  						},
  1298  					},
  1299  				},
  1300  				Timeout: listenerDefaultTimeout,
  1301  			},
  1302  		},
  1303  		Service: &model.Service{
  1304  			Type:             "NodePort",
  1305  			InsecureNodePort: uint32p(30000),
  1306  			SecureNodePort:   uint32p(30001),
  1307  		},
  1308  	},
  1309  }
  1310  
  1311  // multiplePathTypes checks what happens when we have multiple path types in
  1312  // the one Ingress object.
  1313  //
  1314  // Note that there's no sorting done at this point, the sorting is performed
  1315  // in the translation step, not this ingestion step.
  1316  var multiplePathTypes = networkingv1.Ingress{
  1317  	ObjectMeta: metav1.ObjectMeta{
  1318  		Name:      "dummy-ingress",
  1319  		Namespace: "dummy-namespace",
  1320  		UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
  1321  	},
  1322  	Spec: networkingv1.IngressSpec{
  1323  		IngressClassName: stringp("cilium"),
  1324  		Rules: []networkingv1.IngressRule{
  1325  			{
  1326  				IngressRuleValue: networkingv1.IngressRuleValue{
  1327  					HTTP: &networkingv1.HTTPIngressRuleValue{
  1328  						Paths: []networkingv1.HTTPIngressPath{
  1329  							{
  1330  								Path: "/impl",
  1331  								Backend: networkingv1.IngressBackend{
  1332  									Service: &networkingv1.IngressServiceBackend{
  1333  										Name: "dummy-backend",
  1334  										Port: networkingv1.ServiceBackendPort{
  1335  											Number: 8080,
  1336  										},
  1337  									},
  1338  								},
  1339  								PathType: &implementationSpecificPathType,
  1340  							},
  1341  							{
  1342  								Path: "/",
  1343  								Backend: networkingv1.IngressBackend{
  1344  									Service: &networkingv1.IngressServiceBackend{
  1345  										Name: "another-dummy-backend",
  1346  										Port: networkingv1.ServiceBackendPort{
  1347  											Number: 8081,
  1348  										},
  1349  									},
  1350  								},
  1351  								PathType: &prefixPathType,
  1352  							},
  1353  							{
  1354  								Path: "/exact",
  1355  								Backend: networkingv1.IngressBackend{
  1356  									Service: &networkingv1.IngressServiceBackend{
  1357  										Name: "another-dummy-backend",
  1358  										Port: networkingv1.ServiceBackendPort{
  1359  											Number: 8081,
  1360  										},
  1361  									},
  1362  								},
  1363  								PathType: &exactPathType,
  1364  							},
  1365  						},
  1366  					},
  1367  				},
  1368  			},
  1369  		},
  1370  	},
  1371  }
  1372  
  1373  var multiplePathTypesListeners = []model.HTTPListener{
  1374  	{
  1375  		Name: "ing-dummy-ingress-dummy-namespace-*",
  1376  		Sources: []model.FullyQualifiedResource{
  1377  			{
  1378  				Name:      "dummy-ingress",
  1379  				Namespace: "dummy-namespace",
  1380  				Version:   "v1",
  1381  				Kind:      "Ingress",
  1382  				UID:       "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e",
  1383  			},
  1384  		},
  1385  		Port:     80,
  1386  		Hostname: "*",
  1387  		Routes: []model.HTTPRoute{
  1388  			{
  1389  				PathMatch: model.StringMatch{
  1390  					Regex: "/impl",
  1391  				},
  1392  				Backends: []model.Backend{
  1393  					{
  1394  						Name:      "dummy-backend",
  1395  						Namespace: "dummy-namespace",
  1396  						Port: &model.BackendPort{
  1397  							Port: 8080,
  1398  						},
  1399  					},
  1400  				},
  1401  				Timeout: listenerDefaultTimeout,
  1402  			},
  1403  			{
  1404  				PathMatch: model.StringMatch{
  1405  					Prefix: "/",
  1406  				},
  1407  				Backends: []model.Backend{
  1408  					{
  1409  						Name:      "another-dummy-backend",
  1410  						Namespace: "dummy-namespace",
  1411  						Port: &model.BackendPort{
  1412  							Port: 8081,
  1413  						},
  1414  					},
  1415  				},
  1416  				Timeout: listenerDefaultTimeout,
  1417  			},
  1418  			{
  1419  				PathMatch: model.StringMatch{
  1420  					Exact: "/exact",
  1421  				},
  1422  				Backends: []model.Backend{
  1423  					{
  1424  						Name:      "another-dummy-backend",
  1425  						Namespace: "dummy-namespace",
  1426  						Port: &model.BackendPort{
  1427  							Port: 8081,
  1428  						},
  1429  					},
  1430  				},
  1431  				Timeout: listenerDefaultTimeout,
  1432  			},
  1433  		},
  1434  	},
  1435  }
  1436  
  1437  // hostRulesForceHTTPSenabled tests the force-https annotation and should produce
  1438  // three listeners, one for host with no TLS config, then one insecure and one
  1439  // secure for the host with TLS config.
  1440  var hostRulesForceHTTPSenabled = networkingv1.Ingress{
  1441  	ObjectMeta: metav1.ObjectMeta{
  1442  		Name:      "host-rules",
  1443  		Namespace: "random-namespace",
  1444  		Annotations: map[string]string{
  1445  			"ingress.cilium.io/force-https": "enabled",
  1446  		},
  1447  	},
  1448  	Spec: networkingv1.IngressSpec{
  1449  		TLS: []networkingv1.IngressTLS{
  1450  			{
  1451  				Hosts:      []string{"foo.bar.com"},
  1452  				SecretName: "conformance-tls",
  1453  			},
  1454  		},
  1455  		Rules: []networkingv1.IngressRule{
  1456  			{
  1457  				Host: "*.foo.com",
  1458  				IngressRuleValue: networkingv1.IngressRuleValue{
  1459  					HTTP: &networkingv1.HTTPIngressRuleValue{
  1460  						Paths: []networkingv1.HTTPIngressPath{
  1461  							{
  1462  								Path: "/",
  1463  								Backend: networkingv1.IngressBackend{
  1464  									Service: &networkingv1.IngressServiceBackend{
  1465  										Name: "wildcard-foo-com",
  1466  										Port: networkingv1.ServiceBackendPort{
  1467  											Number: 8080,
  1468  										},
  1469  									},
  1470  								},
  1471  								PathType: &prefixPathType,
  1472  							},
  1473  						},
  1474  					},
  1475  				},
  1476  			},
  1477  			{
  1478  				Host: "foo.bar.com",
  1479  				IngressRuleValue: networkingv1.IngressRuleValue{
  1480  					HTTP: &networkingv1.HTTPIngressRuleValue{
  1481  						Paths: []networkingv1.HTTPIngressPath{
  1482  							{
  1483  								Path: "/",
  1484  								Backend: networkingv1.IngressBackend{
  1485  									Service: &networkingv1.IngressServiceBackend{
  1486  										Name: "foo-bar-com",
  1487  										Port: networkingv1.ServiceBackendPort{
  1488  											Name: "http",
  1489  										},
  1490  									},
  1491  								},
  1492  								PathType: &prefixPathType,
  1493  							},
  1494  						},
  1495  					},
  1496  				},
  1497  			},
  1498  		},
  1499  	},
  1500  }
  1501  
  1502  var hostRulesForceHTTPSenabledListeners = []model.HTTPListener{
  1503  	{
  1504  		Name: "ing-host-rules-random-namespace-*.foo.com",
  1505  		Sources: []model.FullyQualifiedResource{
  1506  			{
  1507  				Name:      "host-rules",
  1508  				Namespace: "random-namespace",
  1509  				Version:   "v1",
  1510  				Kind:      "Ingress",
  1511  			},
  1512  		},
  1513  		Port:     80,
  1514  		Hostname: "*.foo.com",
  1515  		Routes: []model.HTTPRoute{
  1516  			{
  1517  				PathMatch: model.StringMatch{
  1518  					Prefix: "/",
  1519  				},
  1520  				Backends: []model.Backend{
  1521  					{
  1522  						Name:      "wildcard-foo-com",
  1523  						Namespace: "random-namespace",
  1524  						Port: &model.BackendPort{
  1525  							Port: 8080,
  1526  						},
  1527  					},
  1528  				},
  1529  				Timeout: listenerDefaultTimeout,
  1530  			},
  1531  		},
  1532  	},
  1533  	{
  1534  		Name: "ing-host-rules-random-namespace-foo.bar.com",
  1535  		Sources: []model.FullyQualifiedResource{
  1536  			{
  1537  				Name:      "host-rules",
  1538  				Namespace: "random-namespace",
  1539  				Version:   "v1",
  1540  				Kind:      "Ingress",
  1541  			},
  1542  		},
  1543  		Port:     80,
  1544  		Hostname: "foo.bar.com",
  1545  		Routes: []model.HTTPRoute{
  1546  			{
  1547  				PathMatch: model.StringMatch{
  1548  					Prefix: "/",
  1549  				},
  1550  				Backends: []model.Backend{
  1551  					{
  1552  						Name:      "foo-bar-com",
  1553  						Namespace: "random-namespace",
  1554  						Port: &model.BackendPort{
  1555  							Name: "http",
  1556  						},
  1557  					},
  1558  				},
  1559  				Timeout: listenerDefaultTimeout,
  1560  			},
  1561  		},
  1562  	},
  1563  	{
  1564  		Name: "ing-host-rules-random-namespace-foo.bar.com",
  1565  		Sources: []model.FullyQualifiedResource{
  1566  			{
  1567  				Name:      "host-rules",
  1568  				Namespace: "random-namespace",
  1569  				Version:   "v1",
  1570  				Kind:      "Ingress",
  1571  			},
  1572  		},
  1573  		Port:     443,
  1574  		Hostname: "foo.bar.com",
  1575  		TLS: []model.TLSSecret{
  1576  			{
  1577  				Name:      "conformance-tls",
  1578  				Namespace: "random-namespace",
  1579  			},
  1580  		},
  1581  		ForceHTTPtoHTTPSRedirect: true,
  1582  		Routes: []model.HTTPRoute{
  1583  			{
  1584  				PathMatch: model.StringMatch{
  1585  					Prefix: "/",
  1586  				},
  1587  				Backends: []model.Backend{
  1588  					{
  1589  						Name:      "foo-bar-com",
  1590  						Namespace: "random-namespace",
  1591  						Port: &model.BackendPort{
  1592  							Name: "http",
  1593  						},
  1594  					},
  1595  				},
  1596  				Timeout: listenerDefaultTimeout,
  1597  			},
  1598  		},
  1599  	},
  1600  }
  1601  
  1602  // forceHTTPSenabled tests the force-https annotation and should produce
  1603  // three listeners, one for host with no TLS config, then one insecure and one
  1604  // secure for the host with TLS config.
  1605  var hostRulesForceHTTPSdisabled = networkingv1.Ingress{
  1606  	ObjectMeta: metav1.ObjectMeta{
  1607  		Name:      "host-rules",
  1608  		Namespace: "random-namespace",
  1609  		Annotations: map[string]string{
  1610  			"ingress.cilium.io/force-https": "disabled",
  1611  		},
  1612  	},
  1613  	Spec: networkingv1.IngressSpec{
  1614  		TLS: []networkingv1.IngressTLS{
  1615  			{
  1616  				Hosts:      []string{"foo.bar.com"},
  1617  				SecretName: "conformance-tls",
  1618  			},
  1619  		},
  1620  		Rules: []networkingv1.IngressRule{
  1621  			{
  1622  				Host: "*.foo.com",
  1623  				IngressRuleValue: networkingv1.IngressRuleValue{
  1624  					HTTP: &networkingv1.HTTPIngressRuleValue{
  1625  						Paths: []networkingv1.HTTPIngressPath{
  1626  							{
  1627  								Path: "/",
  1628  								Backend: networkingv1.IngressBackend{
  1629  									Service: &networkingv1.IngressServiceBackend{
  1630  										Name: "wildcard-foo-com",
  1631  										Port: networkingv1.ServiceBackendPort{
  1632  											Number: 8080,
  1633  										},
  1634  									},
  1635  								},
  1636  								PathType: &prefixPathType,
  1637  							},
  1638  						},
  1639  					},
  1640  				},
  1641  			},
  1642  			{
  1643  				Host: "foo.bar.com",
  1644  				IngressRuleValue: networkingv1.IngressRuleValue{
  1645  					HTTP: &networkingv1.HTTPIngressRuleValue{
  1646  						Paths: []networkingv1.HTTPIngressPath{
  1647  							{
  1648  								Path: "/",
  1649  								Backend: networkingv1.IngressBackend{
  1650  									Service: &networkingv1.IngressServiceBackend{
  1651  										Name: "foo-bar-com",
  1652  										Port: networkingv1.ServiceBackendPort{
  1653  											Name: "http",
  1654  										},
  1655  									},
  1656  								},
  1657  								PathType: &prefixPathType,
  1658  							},
  1659  						},
  1660  					},
  1661  				},
  1662  			},
  1663  		},
  1664  	},
  1665  }
  1666  
  1667  var requestTimeoutAnnotationIngress = networkingv1.Ingress{
  1668  	ObjectMeta: metav1.ObjectMeta{
  1669  		Name:      "load-balancing-request-timeout-annotation",
  1670  		Namespace: "random-namespace",
  1671  		Annotations: map[string]string{
  1672  			"ingress.cilium.io/request-timeout": "10s",
  1673  		},
  1674  	},
  1675  	Spec: networkingv1.IngressSpec{
  1676  		IngressClassName: stringp("cilium"),
  1677  		DefaultBackend: &networkingv1.IngressBackend{
  1678  			Service: &networkingv1.IngressServiceBackend{
  1679  				Name: "default-backend",
  1680  				Port: networkingv1.ServiceBackendPort{
  1681  					Number: 8080,
  1682  				},
  1683  			},
  1684  		},
  1685  	},
  1686  }
  1687  
  1688  var requestTimeoutAnnotationListeners = []model.HTTPListener{
  1689  	{
  1690  		Sources: []model.FullyQualifiedResource{
  1691  			{
  1692  				Name:      "load-balancing-request-timeout-annotation",
  1693  				Namespace: "random-namespace",
  1694  				Version:   "v1",
  1695  				Kind:      "Ingress",
  1696  			},
  1697  		},
  1698  		Port:     80,
  1699  		Hostname: "*",
  1700  		Routes: []model.HTTPRoute{
  1701  			{
  1702  				Backends: []model.Backend{
  1703  					{
  1704  						Name:      "default-backend",
  1705  						Namespace: "random-namespace",
  1706  						Port: &model.BackendPort{
  1707  							Port: 8080,
  1708  						},
  1709  					},
  1710  				},
  1711  				Timeout: model.Timeout{
  1712  					Request: model.AddressOf(time.Second * 10),
  1713  				},
  1714  			},
  1715  		},
  1716  	},
  1717  }
  1718  
  1719  var requestTimeoutInvalidIngress = networkingv1.Ingress{
  1720  	ObjectMeta: metav1.ObjectMeta{
  1721  		Name:      "load-balancing-request-timeout-invalid-annotation",
  1722  		Namespace: "random-namespace",
  1723  		Annotations: map[string]string{
  1724  			"ingress.cilium.io/request-timeout": "invalid-duration",
  1725  		},
  1726  	},
  1727  	Spec: networkingv1.IngressSpec{
  1728  		IngressClassName: stringp("cilium"),
  1729  		DefaultBackend: &networkingv1.IngressBackend{
  1730  			Service: &networkingv1.IngressServiceBackend{
  1731  				Name: "default-backend",
  1732  				Port: networkingv1.ServiceBackendPort{
  1733  					Number: 8080,
  1734  				},
  1735  			},
  1736  		},
  1737  	},
  1738  }
  1739  
  1740  var requestTimeoutInvalidListeners = []model.HTTPListener{
  1741  	{
  1742  		Sources: []model.FullyQualifiedResource{
  1743  			{
  1744  				Name:      "load-balancing-request-timeout-invalid-annotation",
  1745  				Namespace: "random-namespace",
  1746  				Version:   "v1",
  1747  				Kind:      "Ingress",
  1748  			},
  1749  		},
  1750  		Port:     80,
  1751  		Hostname: "*",
  1752  		Routes: []model.HTTPRoute{
  1753  			{
  1754  				Backends: []model.Backend{
  1755  					{
  1756  						Name:      "default-backend",
  1757  						Namespace: "random-namespace",
  1758  						Port: &model.BackendPort{
  1759  							Port: 8080,
  1760  						},
  1761  					},
  1762  				},
  1763  				Timeout: listenerDefaultTimeout,
  1764  			},
  1765  		},
  1766  	},
  1767  }
  1768  
  1769  func stringp(in string) *string {
  1770  	return &in
  1771  }
  1772  
  1773  func uint32p(in uint32) *uint32 {
  1774  	return &in
  1775  }
  1776  
  1777  func removeIngressTLSsecretName(ing networkingv1.Ingress) networkingv1.Ingress {
  1778  	ret := networkingv1.Ingress{}
  1779  	ing.DeepCopyInto(&ret)
  1780  	for i := range ret.Spec.TLS {
  1781  		ret.Spec.TLS[i].SecretName = ""
  1782  	}
  1783  	return ret
  1784  }
  1785  
  1786  func removeListenersTLSsecret(listeners []model.HTTPListener) []model.HTTPListener {
  1787  	ret := []model.HTTPListener{}
  1788  	for _, listener := range listeners {
  1789  		listener.TLS = nil
  1790  		ret = append(ret, listener)
  1791  	}
  1792  	return ret
  1793  }
  1794  
  1795  func useDefaultListenersTLSsecret(listeners []model.HTTPListener) []model.HTTPListener {
  1796  	ret := []model.HTTPListener{}
  1797  	for _, listener := range listeners {
  1798  		if listener.Port == 443 {
  1799  			listener.TLS = []model.TLSSecret{
  1800  				{Namespace: defaultSecretNamespace, Name: defaultSecretName},
  1801  			}
  1802  		}
  1803  		ret = append(ret, listener)
  1804  	}
  1805  	return ret
  1806  }
  1807  
  1808  func removeIngressHTTPRuleValues(ing networkingv1.Ingress) networkingv1.Ingress {
  1809  	var rules []networkingv1.IngressRule
  1810  
  1811  	for _, r := range ing.Spec.Rules {
  1812  		r.HTTP = nil
  1813  		rules = append(rules, r)
  1814  	}
  1815  
  1816  	ret := networkingv1.Ingress{}
  1817  	ing.DeepCopyInto(&ret)
  1818  	ret.Spec.Rules = rules
  1819  
  1820  	return ret
  1821  }
  1822  
  1823  type testcase struct {
  1824  	ingress        networkingv1.Ingress
  1825  	defaultSecret  bool
  1826  	enforceHTTPS   bool
  1827  	requestTimeout time.Duration
  1828  	want           []model.HTTPListener
  1829  }
  1830  
  1831  func TestIngress(t *testing.T) {
  1832  	tests := map[string]testcase{
  1833  		"conformance default backend test": {
  1834  			ingress: defaultBackend,
  1835  			want:    defaultBackendListeners,
  1836  		},
  1837  		"conformance default backend (legacy annotation) test": {
  1838  			ingress: defaultBackendLegacy,
  1839  			want:    defaultBackendListeners,
  1840  		},
  1841  		"conformance default backend (legacy + new) test": {
  1842  			ingress: defaultBackendLegacyOverride,
  1843  			want:    defaultBackendListeners,
  1844  		},
  1845  		"cilium test ingress without http rules": {
  1846  			ingress: removeIngressHTTPRuleValues(hostRules),
  1847  			want:    []model.HTTPListener{},
  1848  		},
  1849  		"conformance host rules test": {
  1850  			ingress: hostRules,
  1851  			want:    hostRulesListeners,
  1852  		},
  1853  		"conformance host rules test without SecretName": {
  1854  			ingress: removeIngressTLSsecretName(hostRules),
  1855  			want:    removeListenersTLSsecret(hostRulesListeners),
  1856  		},
  1857  		"conformance path rules test": {
  1858  			ingress: pathRules,
  1859  			want:    pathRulesListeners,
  1860  		},
  1861  		"cilium test ingress": {
  1862  			ingress: complexIngress,
  1863  			want:    complexIngressListeners,
  1864  		},
  1865  		"cilium test ingress without SecretName": {
  1866  			ingress: removeIngressTLSsecretName(complexIngress),
  1867  			want:    removeListenersTLSsecret(complexIngressListeners),
  1868  		},
  1869  		"cilium test ingress with NodePort": {
  1870  			ingress: complexNodePortIngress,
  1871  			want:    complexNodePortIngressListeners,
  1872  		},
  1873  		"cilium test ingress with NodePort without SecretName": {
  1874  			ingress: removeIngressTLSsecretName(complexNodePortIngress),
  1875  			want:    removeListenersTLSsecret(complexNodePortIngressListeners),
  1876  		},
  1877  		"conformance default backend test with default secret": {
  1878  			ingress:       defaultBackend,
  1879  			defaultSecret: true,
  1880  			want:          defaultBackendListeners,
  1881  		},
  1882  		"conformance default backend (legacy annotation) test with default secret": {
  1883  			ingress:       defaultBackendLegacy,
  1884  			defaultSecret: true,
  1885  			want:          defaultBackendListeners,
  1886  		},
  1887  		"conformance default backend (legacy + new) test with default secret": {
  1888  			ingress:       defaultBackendLegacyOverride,
  1889  			defaultSecret: true,
  1890  			want:          defaultBackendListeners,
  1891  		},
  1892  		"conformance host rules test with default secret": {
  1893  			ingress:       hostRules,
  1894  			defaultSecret: true,
  1895  			want:          hostRulesListeners,
  1896  		},
  1897  		"conformance host rules test with default secret without SecretName": {
  1898  			ingress:       removeIngressTLSsecretName(hostRules),
  1899  			defaultSecret: true,
  1900  			want:          useDefaultListenersTLSsecret(hostRulesListeners),
  1901  		},
  1902  		"conformance path rules test with default secret": {
  1903  			ingress:       pathRules,
  1904  			defaultSecret: true,
  1905  			want:          pathRulesListeners,
  1906  		},
  1907  		"cilium test ingress with default secret": {
  1908  			ingress:       complexIngress,
  1909  			defaultSecret: true,
  1910  			want:          complexIngressListeners,
  1911  		},
  1912  		"cilium test ingress with default secret without SecretName": {
  1913  			ingress:       removeIngressTLSsecretName(complexIngress),
  1914  			defaultSecret: true,
  1915  			want:          useDefaultListenersTLSsecret(complexIngressListeners),
  1916  		},
  1917  		"cilium test ingress with NodePort with default secret": {
  1918  			ingress:       complexNodePortIngress,
  1919  			defaultSecret: true,
  1920  			want:          complexNodePortIngressListeners,
  1921  		},
  1922  		"cilium test ingress with NodePort with default secret without SecretName": {
  1923  			ingress:       removeIngressTLSsecretName(complexNodePortIngress),
  1924  			defaultSecret: true,
  1925  			want:          useDefaultListenersTLSsecret(complexNodePortIngressListeners),
  1926  		},
  1927  		"cilium multiple path types": {
  1928  			ingress: multiplePathTypes,
  1929  			want:    multiplePathTypesListeners,
  1930  		},
  1931  		"force-https annotation present and enabled": {
  1932  			ingress: hostRulesForceHTTPSenabled,
  1933  			want:    hostRulesForceHTTPSenabledListeners,
  1934  		},
  1935  		"force-https annotation present and enabled, enforceHTTPS enabled": {
  1936  			ingress:      hostRulesForceHTTPSenabled,
  1937  			want:         hostRulesForceHTTPSenabledListeners,
  1938  			enforceHTTPS: true,
  1939  		},
  1940  		"force-https annotation present and disabled, enforceHTTPS enabled": {
  1941  			ingress:      hostRulesForceHTTPSdisabled,
  1942  			want:         hostRulesListeners,
  1943  			enforceHTTPS: true,
  1944  		},
  1945  		"force-https annotation present and disabled, enforceHTTPS disabled": {
  1946  			ingress: hostRulesForceHTTPSdisabled,
  1947  			want:    hostRulesListeners,
  1948  		},
  1949  		"force-https annotation not present, enforceHTTPS enabled": {
  1950  			ingress:      hostRules,
  1951  			want:         hostRulesForceHTTPSenabledListeners,
  1952  			enforceHTTPS: true,
  1953  		},
  1954  		"request-timeout flag present with no annotation": {
  1955  			ingress:        defaultBackend,
  1956  			want:           defaultBackendListenersWithRequestTimeout,
  1957  			requestTimeout: time.Second * 10,
  1958  		},
  1959  		"request-timeout annotation present": {
  1960  			ingress: requestTimeoutAnnotationIngress,
  1961  			want:    requestTimeoutAnnotationListeners,
  1962  		},
  1963  		"request-timeout annotation present but invalid": {
  1964  			ingress: requestTimeoutInvalidIngress,
  1965  			want:    requestTimeoutInvalidListeners,
  1966  		},
  1967  	}
  1968  
  1969  	for name, tc := range tests {
  1970  		t.Run(name, func(t *testing.T) {
  1971  			var listeners []model.HTTPListener
  1972  			if tc.defaultSecret {
  1973  				listeners = Ingress(tc.ingress, defaultSecretNamespace, defaultSecretName, tc.enforceHTTPS, 80, 443, tc.requestTimeout)
  1974  			} else {
  1975  				listeners = Ingress(tc.ingress, "", "", tc.enforceHTTPS, 80, 443, tc.requestTimeout)
  1976  			}
  1977  
  1978  			assert.Equal(t, tc.want, listeners, "Listeners did not match")
  1979  		})
  1980  	}
  1981  }
  1982  
  1983  // SSL Passthrough tests
  1984  //
  1985  // Sources for the SSL Passthrough Ingress objects
  1986  var sslPassthruSources = []model.FullyQualifiedResource{
  1987  	{
  1988  		Name:      "sslpassthru-ingress",
  1989  		Namespace: "dummy-namespace",
  1990  		Version:   "v1",
  1991  		Kind:      "Ingress",
  1992  	},
  1993  }
  1994  
  1995  var emptyTLSListeners = []model.TLSPassthroughListener{}
  1996  
  1997  // sslPassthru tests basic SSL Passthrough
  1998  var sslPassthru = networkingv1.Ingress{
  1999  	ObjectMeta: metav1.ObjectMeta{
  2000  		Name:      "sslpassthru-ingress",
  2001  		Namespace: "dummy-namespace",
  2002  		Annotations: map[string]string{
  2003  			"ingress.cilium.io/tls-passthrough": "true",
  2004  		},
  2005  	},
  2006  	Spec: networkingv1.IngressSpec{
  2007  		IngressClassName: stringp("cilium"),
  2008  		Rules: []networkingv1.IngressRule{
  2009  			{
  2010  				Host: "sslpassthru.example.com",
  2011  				IngressRuleValue: networkingv1.IngressRuleValue{
  2012  					HTTP: &networkingv1.HTTPIngressRuleValue{
  2013  						Paths: []networkingv1.HTTPIngressPath{
  2014  							{
  2015  								Path: "/",
  2016  								Backend: networkingv1.IngressBackend{
  2017  									Service: &networkingv1.IngressServiceBackend{
  2018  										Name: "dummy-backend",
  2019  										Port: networkingv1.ServiceBackendPort{
  2020  											Number: 8080,
  2021  										},
  2022  									},
  2023  								},
  2024  								PathType: &exactPathType,
  2025  							},
  2026  						},
  2027  					},
  2028  				},
  2029  			},
  2030  		},
  2031  	},
  2032  }
  2033  
  2034  var sslPassthruTLSListeners = []model.TLSPassthroughListener{
  2035  	{
  2036  		Name:     "ing-sslpassthru-ingress-dummy-namespace-sslpassthru.example.com",
  2037  		Sources:  sslPassthruSources,
  2038  		Port:     443,
  2039  		Hostname: "sslpassthru.example.com",
  2040  		Routes: []model.TLSPassthroughRoute{
  2041  			{
  2042  				Hostnames: []string{
  2043  					"sslpassthru.example.com",
  2044  				},
  2045  				Backends: []model.Backend{
  2046  					{
  2047  						Name:      "dummy-backend",
  2048  						Namespace: "dummy-namespace",
  2049  						Port: &model.BackendPort{
  2050  							Port: 8080,
  2051  						},
  2052  					},
  2053  				},
  2054  			},
  2055  		},
  2056  	},
  2057  }
  2058  
  2059  // sslPassthruNoHost tests when there's no host set
  2060  var sslPassthruNoHost = networkingv1.Ingress{
  2061  	ObjectMeta: metav1.ObjectMeta{
  2062  		Name:      "sslpassthru-ingress",
  2063  		Namespace: "dummy-namespace",
  2064  		Annotations: map[string]string{
  2065  			"ingress.cilium.io/tls-passthrough": "true",
  2066  		},
  2067  	},
  2068  	Spec: networkingv1.IngressSpec{
  2069  		IngressClassName: stringp("cilium"),
  2070  		Rules: []networkingv1.IngressRule{
  2071  			{
  2072  				IngressRuleValue: networkingv1.IngressRuleValue{
  2073  					HTTP: &networkingv1.HTTPIngressRuleValue{
  2074  						Paths: []networkingv1.HTTPIngressPath{
  2075  							{
  2076  								Path: "/",
  2077  								Backend: networkingv1.IngressBackend{
  2078  									Service: &networkingv1.IngressServiceBackend{
  2079  										Name: "dummy-backend",
  2080  										Port: networkingv1.ServiceBackendPort{
  2081  											Number: 8080,
  2082  										},
  2083  									},
  2084  								},
  2085  								PathType: &exactPathType,
  2086  							},
  2087  						},
  2088  					},
  2089  				},
  2090  			},
  2091  		},
  2092  	},
  2093  }
  2094  
  2095  // sslPassthruNoRule tests when there's a hostname but no rule at all
  2096  var sslPassthruNoRule = networkingv1.Ingress{
  2097  	ObjectMeta: metav1.ObjectMeta{
  2098  		Name:      "sslpassthru-ingress",
  2099  		Namespace: "dummy-namespace",
  2100  		Annotations: map[string]string{
  2101  			"ingress.cilium.io/tls-passthrough": "true",
  2102  		},
  2103  	},
  2104  	Spec: networkingv1.IngressSpec{
  2105  		IngressClassName: stringp("cilium"),
  2106  		Rules: []networkingv1.IngressRule{
  2107  			{
  2108  				Host:             "sslpassthru.example.com",
  2109  				IngressRuleValue: networkingv1.IngressRuleValue{},
  2110  			},
  2111  		},
  2112  	},
  2113  }
  2114  
  2115  // sslPassthruExtraPath tests when a hostname and a rule but the path isn't '/'
  2116  var sslPassthruExtraPath = networkingv1.Ingress{
  2117  	ObjectMeta: metav1.ObjectMeta{
  2118  		Name:      "sslpassthru-ingress",
  2119  		Namespace: "dummy-namespace",
  2120  		Annotations: map[string]string{
  2121  			"ingress.cilium.io/tls-passthrough": "true",
  2122  		},
  2123  	},
  2124  	Spec: networkingv1.IngressSpec{
  2125  		IngressClassName: stringp("cilium"),
  2126  		Rules: []networkingv1.IngressRule{
  2127  			{
  2128  				Host: "sslpassthru.example.com",
  2129  				IngressRuleValue: networkingv1.IngressRuleValue{
  2130  					HTTP: &networkingv1.HTTPIngressRuleValue{
  2131  						Paths: []networkingv1.HTTPIngressPath{
  2132  							{
  2133  								Path: "/prefix",
  2134  								Backend: networkingv1.IngressBackend{
  2135  									Service: &networkingv1.IngressServiceBackend{
  2136  										Name: "dummy-backend",
  2137  										Port: networkingv1.ServiceBackendPort{
  2138  											Number: 8080,
  2139  										},
  2140  									},
  2141  								},
  2142  								PathType: &exactPathType,
  2143  							},
  2144  						},
  2145  					},
  2146  				},
  2147  			},
  2148  		},
  2149  	},
  2150  }
  2151  
  2152  // sslPassthruNodePort tests when the Ingress has a NodePort Service set.
  2153  var sslPassthruNodePort = networkingv1.Ingress{
  2154  	ObjectMeta: metav1.ObjectMeta{
  2155  		Name:      "sslpassthru-ingress",
  2156  		Namespace: "dummy-namespace",
  2157  		Annotations: map[string]string{
  2158  			"ingress.cilium.io/service-type":       "NodePort",
  2159  			"ingress.cilium.io/insecure-node-port": "30000",
  2160  			"ingress.cilium.io/secure-node-port":   "30001",
  2161  			"ingress.cilium.io/tls-passthrough":    "true",
  2162  		},
  2163  	},
  2164  	Spec: networkingv1.IngressSpec{
  2165  		IngressClassName: stringp("cilium"),
  2166  		Rules: []networkingv1.IngressRule{
  2167  			{
  2168  				Host: "sslpassthru.example.com",
  2169  				IngressRuleValue: networkingv1.IngressRuleValue{
  2170  					HTTP: &networkingv1.HTTPIngressRuleValue{
  2171  						Paths: []networkingv1.HTTPIngressPath{
  2172  							{
  2173  								Path: "/",
  2174  								Backend: networkingv1.IngressBackend{
  2175  									Service: &networkingv1.IngressServiceBackend{
  2176  										Name: "dummy-backend",
  2177  										Port: networkingv1.ServiceBackendPort{
  2178  											Number: 8080,
  2179  										},
  2180  									},
  2181  								},
  2182  								PathType: &exactPathType,
  2183  							},
  2184  						},
  2185  					},
  2186  				},
  2187  			},
  2188  		},
  2189  	},
  2190  }
  2191  
  2192  var sslPassthruTLSListenersNodePort = []model.TLSPassthroughListener{
  2193  	{
  2194  		Name:     "ing-sslpassthru-ingress-dummy-namespace-sslpassthru.example.com",
  2195  		Sources:  sslPassthruSources,
  2196  		Port:     443,
  2197  		Hostname: "sslpassthru.example.com",
  2198  		Routes: []model.TLSPassthroughRoute{
  2199  			{
  2200  				Hostnames: []string{
  2201  					"sslpassthru.example.com",
  2202  				},
  2203  				Backends: []model.Backend{
  2204  					{
  2205  						Name:      "dummy-backend",
  2206  						Namespace: "dummy-namespace",
  2207  						Port: &model.BackendPort{
  2208  							Port: 8080,
  2209  						},
  2210  					},
  2211  				},
  2212  			},
  2213  		},
  2214  		Service: &model.Service{
  2215  			Type:             "NodePort",
  2216  			InsecureNodePort: uint32p(30000),
  2217  			SecureNodePort:   uint32p(30001),
  2218  		},
  2219  	},
  2220  }
  2221  
  2222  // sslPassthruMultiplePaths tests when there are multiple paths, with one being '/'
  2223  var sslPassthruMultiplePaths = networkingv1.Ingress{
  2224  	ObjectMeta: metav1.ObjectMeta{
  2225  		Name:      "sslpassthru-ingress",
  2226  		Namespace: "dummy-namespace",
  2227  		Annotations: map[string]string{
  2228  			"ingress.cilium.io/tls-passthrough": "true",
  2229  		},
  2230  	},
  2231  	Spec: networkingv1.IngressSpec{
  2232  		IngressClassName: stringp("cilium"),
  2233  		Rules: []networkingv1.IngressRule{
  2234  			{
  2235  				Host: "sslpassthru.example.com",
  2236  				IngressRuleValue: networkingv1.IngressRuleValue{
  2237  					HTTP: &networkingv1.HTTPIngressRuleValue{
  2238  						Paths: []networkingv1.HTTPIngressPath{
  2239  							{
  2240  								Path: "/prefix",
  2241  								Backend: networkingv1.IngressBackend{
  2242  									Service: &networkingv1.IngressServiceBackend{
  2243  										Name: "dummy-backend",
  2244  										Port: networkingv1.ServiceBackendPort{
  2245  											Number: 8080,
  2246  										},
  2247  									},
  2248  								},
  2249  								PathType: &exactPathType,
  2250  							},
  2251  							{
  2252  								Path: "/",
  2253  								Backend: networkingv1.IngressBackend{
  2254  									Service: &networkingv1.IngressServiceBackend{
  2255  										Name: "dummy-backend",
  2256  										Port: networkingv1.ServiceBackendPort{
  2257  											Number: 8080,
  2258  										},
  2259  									},
  2260  								},
  2261  								PathType: &exactPathType,
  2262  							},
  2263  						},
  2264  					},
  2265  				},
  2266  			},
  2267  		},
  2268  	},
  2269  }
  2270  
  2271  var sslPassthruMultiplePathsTLSListeners = []model.TLSPassthroughListener{
  2272  	{
  2273  		Name:     "ing-sslpassthru-ingress-dummy-namespace-sslpassthru.example.com",
  2274  		Sources:  sslPassthruSources,
  2275  		Port:     443,
  2276  		Hostname: "sslpassthru.example.com",
  2277  		Routes: []model.TLSPassthroughRoute{
  2278  			{
  2279  				Hostnames: []string{
  2280  					"sslpassthru.example.com",
  2281  				},
  2282  				Backends: []model.Backend{
  2283  					{
  2284  						Name:      "dummy-backend",
  2285  						Namespace: "dummy-namespace",
  2286  						Port: &model.BackendPort{
  2287  							Port: 8080,
  2288  						},
  2289  					},
  2290  				},
  2291  			},
  2292  		},
  2293  	},
  2294  }
  2295  
  2296  // sslPassthruDefaultBackend tests when there's a default backend supplied
  2297  var sslPassthruDefaultBackend = networkingv1.Ingress{
  2298  	ObjectMeta: metav1.ObjectMeta{
  2299  		Name:      "sslpassthru-ingress",
  2300  		Namespace: "dummy-namespace",
  2301  		Annotations: map[string]string{
  2302  			"ingress.cilium.io/tls-passthrough": "true",
  2303  		},
  2304  	},
  2305  	Spec: networkingv1.IngressSpec{
  2306  		IngressClassName: stringp("cilium"),
  2307  		DefaultBackend: &networkingv1.IngressBackend{
  2308  			Service: &networkingv1.IngressServiceBackend{
  2309  				Name: "default-backend",
  2310  				Port: networkingv1.ServiceBackendPort{
  2311  					Number: 8080,
  2312  				},
  2313  			},
  2314  		},
  2315  		Rules: []networkingv1.IngressRule{},
  2316  	},
  2317  }
  2318  
  2319  type passthruTestcase struct {
  2320  	ingress networkingv1.Ingress
  2321  	want    []model.TLSPassthroughListener
  2322  }
  2323  
  2324  func TestIngressPassthrough(t *testing.T) {
  2325  	tests := map[string]passthruTestcase{
  2326  		"Cilium test ingress with SSL Passthrough": {
  2327  			ingress: sslPassthru,
  2328  			want:    sslPassthruTLSListeners,
  2329  		},
  2330  		"Cilium test ingress with SSL Passthrough, no host set": {
  2331  			ingress: sslPassthruNoHost,
  2332  			want:    emptyTLSListeners,
  2333  		},
  2334  		"Cilium test ingress with SSL Passthrough, host but no rule": {
  2335  			ingress: sslPassthruNoRule,
  2336  			want:    emptyTLSListeners,
  2337  		},
  2338  		"Cilium test ingress with SSL Passthrough, prefix path rule": {
  2339  			ingress: sslPassthruExtraPath,
  2340  			want:    emptyTLSListeners,
  2341  		},
  2342  		"Cilium test ingress with SSL Passthrough and default backend": {
  2343  			ingress: sslPassthruDefaultBackend,
  2344  			want:    emptyTLSListeners,
  2345  		},
  2346  		"Cilium test ingress with SSL Passthrough, multiple path rules, one valid": {
  2347  			ingress: sslPassthruMultiplePaths,
  2348  			want:    sslPassthruMultiplePathsTLSListeners,
  2349  		},
  2350  		"Cilium test ingress with SSL Passthrough, Nodeport Service annotations": {
  2351  			ingress: sslPassthruNodePort,
  2352  			want:    sslPassthruTLSListenersNodePort,
  2353  		},
  2354  	}
  2355  
  2356  	for name, tc := range tests {
  2357  		t.Run(name, func(t *testing.T) {
  2358  			listeners := IngressPassthrough(tc.ingress, 443)
  2359  
  2360  			assert.Equal(t, tc.want, listeners, "Listeners did not match")
  2361  		})
  2362  	}
  2363  }