diff --git a/internal/state/dataplane/configuration.go b/internal/state/dataplane/configuration.go index 02b17b9a8..1eb4342ab 100644 --- a/internal/state/dataplane/configuration.go +++ b/internal/state/dataplane/configuration.go @@ -267,10 +267,9 @@ func (hpr *hostPathRules) upsertListener(l *graph.Listener) { for routeNsName, r := range l.Routes { var hostnames []string - - for _, h := range r.Source.Spec.Hostnames { - if _, exist := l.AcceptedHostnames[string(h)]; exist { - hostnames = append(hostnames, string(h)) + for _, p := range r.ParentRefs { + if val, exist := p.Attachment.AcceptedHostnames[string(l.Source.Name)]; exist { + hostnames = val } } diff --git a/internal/state/dataplane/configuration_test.go b/internal/state/dataplane/configuration_test.go index 0e5029666..6fefb6920 100644 --- a/internal/state/dataplane/configuration_test.go +++ b/internal/state/dataplane/configuration_test.go @@ -130,11 +130,25 @@ func TestBuildConfiguration(t *testing.T) { createInternalRoute := func( source *v1beta1.HTTPRoute, + listenerName string, paths []pathAndType, ) *graph.Route { + hostnames := make([]string, 0, len(source.Spec.Hostnames)) + for _, h := range source.Spec.Hostnames { + hostnames = append(hostnames, string(h)) + } r := &graph.Route{ Source: source, Rules: createRules(source, paths), + ParentRefs: []graph.ParentRef{ + { + Attachment: &graph.ParentRefAttachmentStatus{ + AcceptedHostnames: map[string][]string{ + listenerName: hostnames, + }, + }, + }, + }, } return r } @@ -162,7 +176,7 @@ func TestBuildConfiguration(t *testing.T) { *v1beta1.HTTPRoute, []BackendGroup, *graph.Route, ) { hr := createRoute(name, hostname, listenerName, paths...) - route := createInternalRoute(hr, paths) + route := createInternalRoute(hr, listenerName, paths) groups := createExpBackendGroupsForRoute(route) return hr, groups, route } @@ -217,7 +231,7 @@ func TestBuildConfiguration(t *testing.T) { pathAndType{path: "/valid", pathType: prefix}, pathAndType{path: invalidMatchesPath, pathType: prefix}, ) - hr7, hr7Groups, routeHR7 := createTestResources( + hr7, expHR7Groups, routeHR7 := createTestResources( "hr-7", "foo.example.com", "listener-80-1", @@ -258,6 +272,8 @@ func TestBuildConfiguration(t *testing.T) { "listener-443-with-hostname", pathAndType{path: "/", pathType: prefix}, ) + // add extra attachment for this route for duplicate listener test + httpsRouteHR5.ParentRefs[0].Attachment.AcceptedHostnames["listener-443-1"] = []string{"example.com"} httpsHR6, expHTTPSHR6Groups, httpsRouteHR6 := createTestResources( "https-hr-6", @@ -352,10 +368,9 @@ func TestBuildConfiguration(t *testing.T) { Source: &v1beta1.Gateway{}, Listeners: map[string]*graph.Listener{ "listener-80-1": { - Source: listener80, - Valid: true, - Routes: map[types.NamespacedName]*graph.Route{}, - AcceptedHostnames: map[string]struct{}{}, + Source: listener80, + Valid: true, + Routes: map[types.NamespacedName]*graph.Route{}, }, }, }, @@ -381,18 +396,16 @@ func TestBuildConfiguration(t *testing.T) { Source: &v1beta1.Gateway{}, Listeners: map[string]*graph.Listener{ "listener-443-1": { - Source: listener443, // nil hostname - Valid: true, - Routes: map[types.NamespacedName]*graph.Route{}, - AcceptedHostnames: map[string]struct{}{}, - SecretPath: secretPath, + Source: listener443, // nil hostname + Valid: true, + Routes: map[types.NamespacedName]*graph.Route{}, + SecretPath: secretPath, }, "listener-443-with-hostname": { - Source: listener443WithHostname, // non-nil hostname - Valid: true, - Routes: map[types.NamespacedName]*graph.Route{}, - AcceptedHostnames: map[string]struct{}{}, - SecretPath: secretPath, + Source: listener443WithHostname, // non-nil hostname + Valid: true, + Routes: map[types.NamespacedName]*graph.Route{}, + SecretPath: secretPath, }, }, }, @@ -458,10 +471,6 @@ func TestBuildConfiguration(t *testing.T) { {Namespace: "test", Name: "hr-1"}: routeHR1, {Namespace: "test", Name: "hr-2"}: routeHR2, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - "bar.example.com": {}, - }, }, }, }, @@ -533,10 +542,6 @@ func TestBuildConfiguration(t *testing.T) { {Namespace: "test", Name: "https-hr-1"}: httpsRouteHR1, {Namespace: "test", Name: "https-hr-2"}: httpsRouteHR2, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - "bar.example.com": {}, - }, }, "listener-443-with-hostname": { Source: listener443WithHostname, @@ -545,9 +550,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "https-hr-5"}: httpsRouteHR5, }, - AcceptedHostnames: map[string]struct{}{ - "example.com": {}, - }, }, }, }, @@ -649,9 +651,6 @@ func TestBuildConfiguration(t *testing.T) { {Namespace: "test", Name: "hr-3"}: routeHR3, {Namespace: "test", Name: "hr-4"}: routeHR4, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, "listener-443-1": { Source: listener443, @@ -661,9 +660,6 @@ func TestBuildConfiguration(t *testing.T) { {Namespace: "test", Name: "https-hr-3"}: httpsRouteHR3, {Namespace: "test", Name: "https-hr-4"}: httpsRouteHR4, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, }, }, @@ -815,9 +811,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "hr-1"}: routeHR1, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, }, }, @@ -840,9 +833,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "hr-1"}: routeHR1, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, }, }, @@ -880,9 +870,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "hr-5"}: routeHR5, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, }, }, @@ -952,9 +939,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "hr-6"}: routeHR6, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, "listener-443-1": { Source: listener443, @@ -963,9 +947,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "https-hr-6"}: httpsRouteHR6, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, }, }, @@ -1049,9 +1030,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "hr-7"}: routeHR7, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, }, }, @@ -1074,7 +1052,7 @@ func TestBuildConfiguration(t *testing.T) { { MatchIdx: 0, RuleIdx: 1, - BackendGroup: hr7Groups[1], + BackendGroup: expHR7Groups[1], Source: hr7, }, }, @@ -1086,7 +1064,7 @@ func TestBuildConfiguration(t *testing.T) { { MatchIdx: 0, RuleIdx: 0, - BackendGroup: hr7Groups[0], + BackendGroup: expHR7Groups[0], Source: hr7, }, }, @@ -1096,7 +1074,7 @@ func TestBuildConfiguration(t *testing.T) { }, SSLServers: []VirtualServer{}, Upstreams: []Upstream{fooUpstream}, - BackendGroups: []BackendGroup{hr7Groups[0], hr7Groups[1]}, + BackendGroups: []BackendGroup{expHR7Groups[0], expHR7Groups[1]}, }, msg: "duplicate paths with different types", }, @@ -1116,9 +1094,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "https-hr-5"}: httpsRouteHR5, }, - AcceptedHostnames: map[string]struct{}{ - "example.com": {}, - }, }, "listener-443-1": { Source: listener443, @@ -1127,9 +1102,6 @@ func TestBuildConfiguration(t *testing.T) { Routes: map[types.NamespacedName]*graph.Route{ {Namespace: "test", Name: "https-hr-5"}: httpsRouteHR5, }, - AcceptedHostnames: map[string]struct{}{ - "example.com": {}, - }, }, }, }, diff --git a/internal/state/graph/gateway_listener.go b/internal/state/graph/gateway_listener.go index 7c97c6ae3..5bf859c59 100644 --- a/internal/state/graph/gateway_listener.go +++ b/internal/state/graph/gateway_listener.go @@ -19,9 +19,6 @@ type Listener struct { // Routes holds the routes attached to the Listener. // Only valid routes are attached. Routes map[types.NamespacedName]*Route - // AcceptedHostnames is an intersection between the hostnames supported by the Listener and the hostnames - // from the attached routes. - AcceptedHostnames map[string]struct{} // SecretPath is the path to the secret on disk. SecretPath string // Conditions holds the conditions of the Listener. @@ -147,10 +144,9 @@ func (c *listenerConfigurator) configure(listener v1beta1.Listener) *Listener { } l := &Listener{ - Source: listener, - Routes: make(map[types.NamespacedName]*Route), - AcceptedHostnames: make(map[string]struct{}), - Valid: true, + Source: listener, + Routes: make(map[types.NamespacedName]*Route), + Valid: true, } // resolvers might add different conditions to the listener, so we run them all. diff --git a/internal/state/graph/gateway_test.go b/internal/state/graph/gateway_test.go index 20ad44e8d..c1cc34a6c 100644 --- a/internal/state/graph/gateway_test.go +++ b/internal/state/graph/gateway_test.go @@ -298,10 +298,9 @@ func TestBuildGateway(t *testing.T) { Source: getLastCreatedGetaway(), Listeners: map[string]*Listener{ "listener-80-1": { - Source: listener801, - Valid: true, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, + Source: listener801, + Valid: true, + Routes: map[types.NamespacedName]*Route{}, }, }, Valid: true, @@ -315,11 +314,10 @@ func TestBuildGateway(t *testing.T) { Source: getLastCreatedGetaway(), Listeners: map[string]*Listener{ "listener-443-1": { - Source: listener4431, - Valid: true, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, - SecretPath: secretPath, + Source: listener4431, + Valid: true, + Routes: map[types.NamespacedName]*Route{}, + SecretPath: secretPath, }, }, Valid: true, @@ -418,10 +416,9 @@ func TestBuildGateway(t *testing.T) { Source: getLastCreatedGetaway(), Listeners: map[string]*Listener{ "listener-443-5": { - Source: listener4435, - Valid: false, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, + Source: listener4435, + Valid: false, + Routes: map[types.NamespacedName]*Route{}, Conditions: conditions.NewListenerInvalidCertificateRef( `tls.certificateRefs[0]: Invalid value: test/does-not-exist: secret not found`, ), @@ -440,30 +437,26 @@ func TestBuildGateway(t *testing.T) { Source: getLastCreatedGetaway(), Listeners: map[string]*Listener{ "listener-80-1": { - Source: listener801, - Valid: true, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, + Source: listener801, + Valid: true, + Routes: map[types.NamespacedName]*Route{}, }, "listener-80-3": { - Source: listener803, - Valid: true, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, + Source: listener803, + Valid: true, + Routes: map[types.NamespacedName]*Route{}, }, "listener-443-1": { - Source: listener4431, - Valid: true, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, - SecretPath: secretPath, + Source: listener4431, + Valid: true, + Routes: map[types.NamespacedName]*Route{}, + SecretPath: secretPath, }, "listener-443-2": { - Source: listener4432, - Valid: true, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, - SecretPath: secretPath, + Source: listener4432, + Valid: true, + Routes: map[types.NamespacedName]*Route{}, + SecretPath: secretPath, }, }, Valid: true, @@ -479,34 +472,30 @@ func TestBuildGateway(t *testing.T) { Source: getLastCreatedGetaway(), Listeners: map[string]*Listener{ "listener-80-1": { - Source: listener801, - Valid: false, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, - Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), + Source: listener801, + Valid: false, + Routes: map[types.NamespacedName]*Route{}, + Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), }, "listener-80-4": { - Source: listener804, - Valid: false, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, - Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), + Source: listener804, + Valid: false, + Routes: map[types.NamespacedName]*Route{}, + Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), }, "listener-443-1": { - Source: listener4431, - Valid: false, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, - Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), - SecretPath: "/etc/nginx/secrets/test_secret", + Source: listener4431, + Valid: false, + Routes: map[types.NamespacedName]*Route{}, + Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), + SecretPath: "/etc/nginx/secrets/test_secret", }, "listener-443-3": { - Source: listener4433, - Valid: false, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, - Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), - SecretPath: "/etc/nginx/secrets/test_secret", + Source: listener4433, + Valid: false, + Routes: map[types.NamespacedName]*Route{}, + Conditions: conditions.NewListenerConflictedHostname(conflictedHostnamesMsg), + SecretPath: "/etc/nginx/secrets/test_secret", }, }, Valid: true, diff --git a/internal/state/graph/graph_test.go b/internal/state/graph/graph_test.go index 7b292a88b..1787338bd 100644 --- a/internal/state/graph/graph_test.go +++ b/internal/state/graph/graph_test.go @@ -173,7 +173,8 @@ func TestBuildGraph(t *testing.T) { Idx: 0, Gateway: client.ObjectKeyFromObject(gw1), Attachment: &ParentRefAttachmentStatus{ - Attached: true, + Attached: true, + AcceptedHostnames: map[string][]string{"listener-80-1": {"foo.example.com"}}, }, }, }, @@ -188,7 +189,8 @@ func TestBuildGraph(t *testing.T) { Idx: 0, Gateway: client.ObjectKeyFromObject(gw1), Attachment: &ParentRefAttachmentStatus{ - Attached: true, + Attached: true, + AcceptedHostnames: map[string][]string{"listener-443-1": {"foo.example.com"}}, }, }, }, @@ -218,9 +220,6 @@ func TestBuildGraph(t *testing.T) { Routes: map[types.NamespacedName]*Route{ {Namespace: "test", Name: "hr-1"}: routeHR1, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, }, "listener-443-1": { Source: gw1.Spec.Listeners[1], @@ -228,9 +227,6 @@ func TestBuildGraph(t *testing.T) { Routes: map[types.NamespacedName]*Route{ {Namespace: "test", Name: "hr-3"}: routeHR3, }, - AcceptedHostnames: map[string]struct{}{ - "foo.example.com": {}, - }, SecretPath: secretPath, }, }, diff --git a/internal/state/graph/httproute.go b/internal/state/graph/httproute.go index 02990edb0..64f13db9a 100644 --- a/internal/state/graph/httproute.go +++ b/internal/state/graph/httproute.go @@ -13,6 +13,8 @@ import ( "github.com/nginxinc/nginx-kubernetes-gateway/internal/state/validation" ) +const wildcardHostname = "~^" + // Rule represents a rule of an HTTPRoute. type Rule struct { // BackendRefs is a list of BackendRefs for the rule. @@ -38,6 +40,9 @@ type ParentRef struct { // ParentRefAttachmentStatus describes the attachment status of a ParentRef. type ParentRefAttachmentStatus struct { + // AcceptedHostnames is an intersection between the hostnames supported by an attached Listener + // and the hostnames from this Route. Key is listener name, value is list of hostnames. + AcceptedHostnames map[string][]string // FailedCondition is the condition that describes why the ParentRef is not attached to the Gateway. It is set // when Attached is false. FailedCondition conditions.Condition @@ -256,7 +261,9 @@ func bindRouteToListeners(r *Route, gw *Gateway) { } for i := 0; i < len(r.ParentRefs); i++ { - attachment := &ParentRefAttachmentStatus{} + attachment := &ParentRefAttachmentStatus{ + AcceptedHostnames: make(map[string][]string), + } ref := &r.ParentRefs[i] ref.Attachment = attachment @@ -291,7 +298,7 @@ func bindRouteToListeners(r *Route, gw *Gateway) { // Case 4 - winning Gateway // Try to attach Route to all matching listeners - cond, attached := tryToAttachRouteToListeners(routeRef, r, gw.Listeners) + cond, attached := tryToAttachRouteToListeners(ref.Attachment, routeRef.SectionName, r, gw.Listeners) if !attached { attachment.FailedCondition = cond continue @@ -308,11 +315,12 @@ func bindRouteToListeners(r *Route, gw *Gateway) { // For now, let's do simple matching. // However, we need to also support wildcard matching. func tryToAttachRouteToListeners( - ref v1beta1.ParentReference, + refStatus *ParentRefAttachmentStatus, + sectionName *v1beta1.SectionName, route *Route, listeners map[string]*Listener, ) (conditions.Condition, bool) { - validListeners, listenerExists := findValidListeners(getSectionName(ref.SectionName), listeners) + validListeners, listenerExists := findValidListeners(getSectionName(sectionName), listeners) if !listenerExists { // FIXME(pleshakov): Add a proper condition once it is available in the Gateway API. @@ -330,9 +338,7 @@ func tryToAttachRouteToListeners( return false } - for _, h := range hostnames { - l.AcceptedHostnames[h] = struct{}{} - } + refStatus.AcceptedHostnames[string(l.Source.Name)] = hostnames l.Routes[client.ObjectKeyFromObject(route.Source)] = route return true @@ -380,6 +386,13 @@ func findValidListeners(sectionName string, listeners map[string]*Listener) ([]* func findAcceptedHostnames(listenerHostname *v1beta1.Hostname, routeHostnames []v1beta1.Hostname) []string { hostname := getHostname(listenerHostname) + if len(routeHostnames) == 0 { + if hostname == "" { + return []string{wildcardHostname} + } + return []string{hostname} + } + match := func(h v1beta1.Hostname) bool { if hostname == "" { return true diff --git a/internal/state/graph/httproute_test.go b/internal/state/graph/httproute_test.go index 80f96f4ce..8a129da6c 100644 --- a/internal/state/graph/httproute_test.go +++ b/internal/state/graph/httproute_test.go @@ -530,18 +530,18 @@ func TestBuildRoute(t *testing.T) { func TestBindRouteToListeners(t *testing.T) { // we create a new listener each time because the function under test can modify it - createListener := func() *Listener { + createListener := func(name string) *Listener { return &Listener{ Source: v1beta1.Listener{ + Name: v1beta1.SectionName(name), Hostname: (*v1beta1.Hostname)(helpers.GetStringPointer("foo.example.com")), }, - Valid: true, - Routes: map[types.NamespacedName]*Route{}, - AcceptedHostnames: map[string]struct{}{}, + Valid: true, + Routes: map[types.NamespacedName]*Route{}, } } - createModifiedListener := func(m func(*Listener)) *Listener { - l := createListener() + createModifiedListener := func(name string, m func(*Listener)) *Listener { + l := createListener(name) m(l) return l } @@ -670,10 +670,10 @@ func TestBindRouteToListeners(t *testing.T) { }, } - notValidListener := createModifiedListener(func(l *Listener) { + notValidListener := createModifiedListener("", func(l *Listener) { l.Valid = false }) - nonMatchingHostnameListener := createModifiedListener(func(l *Listener) { + nonMatchingHostnameListener := createModifiedListener("", func(l *Listener) { l.Source.Hostname = helpers.GetPointer[v1beta1.Hostname]("bar.example.com") }) @@ -690,7 +690,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: true, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -699,17 +699,17 @@ func TestBindRouteToListeners(t *testing.T) { Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ Attached: true, + AcceptedHostnames: map[string][]string{ + "listener-80-1": {"foo.example.com"}, + }, }, }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createModifiedListener(func(l *Listener) { + "listener-80-1": createModifiedListener("listener-80-1", func(l *Listener) { l.Routes = map[types.NamespacedName]*Route{ client.ObjectKeyFromObject(hr): getLastNormalRoute(), } - l.AcceptedHostnames = map[string]struct{}{ - "foo.example.com": {}, - } }), }, name: "normal case", @@ -720,7 +720,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: true, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -729,17 +729,17 @@ func TestBindRouteToListeners(t *testing.T) { Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ Attached: true, + AcceptedHostnames: map[string][]string{ + "listener-80-1": {"foo.example.com"}, + }, }, }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createModifiedListener(func(l *Listener) { + "listener-80-1": createModifiedListener("listener-80-1", func(l *Listener) { l.Routes = map[types.NamespacedName]*Route{ client.ObjectKeyFromObject(hr): routeWithMissingSectionName, } - l.AcceptedHostnames = map[string]struct{}{ - "foo.example.com": {}, - } }), }, name: "section name is nil", @@ -750,7 +750,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: true, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -759,17 +759,17 @@ func TestBindRouteToListeners(t *testing.T) { Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ Attached: true, + AcceptedHostnames: map[string][]string{ + "listener-80-1": {"foo.example.com"}, + }, }, }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createModifiedListener(func(l *Listener) { + "listener-80-1": createModifiedListener("listener-80-1", func(l *Listener) { l.Routes = map[types.NamespacedName]*Route{ client.ObjectKeyFromObject(hr): routeWithEmptySectionName, } - l.AcceptedHostnames = map[string]struct{}{ - "foo.example.com": {}, - } }), }, name: "section name is empty", @@ -788,8 +788,9 @@ func TestBindRouteToListeners(t *testing.T) { Idx: 0, Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ - Attached: false, - FailedCondition: conditions.NewRouteInvalidListener(), + Attached: false, + FailedCondition: conditions.NewRouteInvalidListener(), + AcceptedHostnames: map[string][]string{}, }, }, }, @@ -804,7 +805,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: true, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -816,11 +817,12 @@ func TestBindRouteToListeners(t *testing.T) { FailedCondition: conditions.NewRouteUnsupportedValue( `spec.parentRefs[0].port: Forbidden: cannot be set`, ), + AcceptedHostnames: map[string][]string{}, }, }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, name: "port is configured", }, @@ -830,7 +832,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: true, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -838,13 +840,14 @@ func TestBindRouteToListeners(t *testing.T) { Idx: 0, Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ - Attached: false, - FailedCondition: conditions.NewTODO("listener is not found"), + Attached: false, + FailedCondition: conditions.NewTODO("listener is not found"), + AcceptedHostnames: map[string][]string{}, }, }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, name: "listener doesn't exist", }, @@ -862,8 +865,9 @@ func TestBindRouteToListeners(t *testing.T) { Idx: 0, Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ - Attached: false, - FailedCondition: conditions.NewRouteInvalidListener(), + Attached: false, + FailedCondition: conditions.NewRouteInvalidListener(), + AcceptedHostnames: map[string][]string{}, }, }, }, @@ -886,8 +890,9 @@ func TestBindRouteToListeners(t *testing.T) { Idx: 0, Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ - Attached: false, - FailedCondition: conditions.NewRouteNoMatchingListenerHostname(), + Attached: false, + FailedCondition: conditions.NewRouteNoMatchingListenerHostname(), + AcceptedHostnames: map[string][]string{}, }, }, }, @@ -902,7 +907,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: true, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -910,13 +915,14 @@ func TestBindRouteToListeners(t *testing.T) { Idx: 0, Gateway: ignoredGwNsName, Attachment: &ParentRefAttachmentStatus{ - Attached: false, - FailedCondition: conditions.NewTODO("Gateway is ignored"), + Attached: false, + FailedCondition: conditions.NewTODO("Gateway is ignored"), + AcceptedHostnames: map[string][]string{}, }, }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, name: "gateway is ignored", }, @@ -926,7 +932,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: true, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -937,7 +943,7 @@ func TestBindRouteToListeners(t *testing.T) { }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, name: "route isn't valid", }, @@ -947,7 +953,7 @@ func TestBindRouteToListeners(t *testing.T) { Source: gw, Valid: false, Listeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, }, expectedSectionNameRefs: []ParentRef{ @@ -955,13 +961,14 @@ func TestBindRouteToListeners(t *testing.T) { Idx: 0, Gateway: client.ObjectKeyFromObject(gw), Attachment: &ParentRefAttachmentStatus{ - Attached: false, - FailedCondition: conditions.NewRouteInvalidGateway(), + Attached: false, + FailedCondition: conditions.NewRouteInvalidGateway(), + AcceptedHostnames: map[string][]string{}, }, }, }, expectedGatewayListeners: map[string]*Listener{ - "listener-80-1": createListener(), + "listener-80-1": createListener("listener-80-1"), }, name: "invalid gateway", }, @@ -1008,6 +1015,18 @@ func TestFindAcceptedHostnames(t *testing.T) { expected: []string{"foo.example.com", "bar.example.com"}, msg: "nil listener hostname", }, + { + listenerHostname: &listenerHostnameFoo, + routeHostnames: nil, + expected: []string{"foo.example.com"}, + msg: "route has empty hostnames", + }, + { + listenerHostname: nil, + routeHostnames: nil, + expected: []string{wildcardHostname}, + msg: "both listener and route have empty hostnames", + }, } for _, test := range tests {