Skip to content

Commit fa0d942

Browse files
committed
Allow empty HTTPRoute hostnames
If an HTTPRoute didn't supply any hostnames, then we wouldn't attach it to any listeners. This fixes that issue and uses the wildcard hostname if a listener doesn't supply a hostname, otherwise just use the hostnames of the listeners.
1 parent be51e36 commit fa0d942

File tree

4 files changed

+105
-11
lines changed

4 files changed

+105
-11
lines changed

internal/state/dataplane/configuration.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,7 @@ func (hpr *hostPathRules) upsertListener(l *graph.Listener) {
266266
}
267267

268268
for routeNsName, r := range l.Routes {
269-
var hostnames []string
270-
271-
for _, h := range r.Source.Spec.Hostnames {
272-
if _, exist := l.AcceptedHostnames[string(h)]; exist {
273-
hostnames = append(hostnames, string(h))
274-
}
275-
}
269+
hostnames := getHostnames(r, l)
276270

277271
for _, h := range hostnames {
278272
if prevListener, exists := hpr.listenersForHost[h]; exists {
@@ -333,6 +327,23 @@ func (hpr *hostPathRules) upsertListener(l *graph.Listener) {
333327
}
334328
}
335329

330+
func getHostnames(r *graph.Route, l *graph.Listener) []string {
331+
var hostnames []string
332+
for _, h := range r.Source.Spec.Hostnames {
333+
if _, exist := l.AcceptedHostnames[string(h)]; exist {
334+
hostnames = append(hostnames, string(h))
335+
}
336+
}
337+
338+
if len(r.Source.Spec.Hostnames) == 0 {
339+
for hostname := range l.AcceptedHostnames {
340+
hostnames = append(hostnames, hostname)
341+
}
342+
}
343+
344+
return hostnames
345+
}
346+
336347
func (hpr *hostPathRules) buildServers() []VirtualServer {
337348
servers := make([]VirtualServer, 0, len(hpr.rulesPerHost)+len(hpr.httpsListeners))
338349

internal/state/dataplane/configuration_test.go

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,21 @@ func TestBuildConfiguration(t *testing.T) {
217217
pathAndType{path: "/valid", pathType: prefix}, pathAndType{path: invalidMatchesPath, pathType: prefix},
218218
)
219219

220-
hr7, hr7Groups, routeHR7 := createTestResources(
220+
hr7, expHR7Groups, routeHR7 := createTestResources(
221221
"hr-7",
222222
"foo.example.com",
223223
"listener-80-1",
224224
pathAndType{path: "/valid", pathType: prefix}, pathAndType{path: "/valid", pathType: v1beta1.PathMatchExact},
225225
)
226226

227+
hrNoHost, expHRNoHostGroups, routeNoHost := createTestResources(
228+
"route-no-host",
229+
"",
230+
"listener-80-1",
231+
pathAndType{path: "/", pathType: prefix},
232+
)
233+
routeNoHost.Source.Spec.Hostnames = []v1beta1.Hostname{}
234+
227235
httpsHR1, expHTTPSHR1Groups, httpsRouteHR1 := createTestResources(
228236
"https-hr-1",
229237
"foo.example.com",
@@ -516,6 +524,60 @@ func TestBuildConfiguration(t *testing.T) {
516524
},
517525
msg: "one http listener with two routes for different hostnames",
518526
},
527+
{
528+
graph: &graph.Graph{
529+
GatewayClass: &graph.GatewayClass{
530+
Source: &v1beta1.GatewayClass{},
531+
Valid: true,
532+
},
533+
Gateway: &graph.Gateway{
534+
Source: &v1beta1.Gateway{},
535+
Listeners: map[string]*graph.Listener{
536+
"listener-80-1": {
537+
Source: listener80,
538+
Valid: true,
539+
Routes: map[types.NamespacedName]*graph.Route{
540+
{Namespace: "test", Name: "route-no-host"}: routeNoHost,
541+
},
542+
AcceptedHostnames: map[string]struct{}{
543+
wildcardHostname: {},
544+
},
545+
},
546+
},
547+
},
548+
Routes: map[types.NamespacedName]*graph.Route{
549+
{Namespace: "test", Name: "route-no-host"}: routeNoHost,
550+
},
551+
},
552+
expConf: Configuration{
553+
HTTPServers: []VirtualServer{
554+
{
555+
IsDefault: true,
556+
},
557+
{
558+
Hostname: wildcardHostname,
559+
PathRules: []PathRule{
560+
{
561+
Path: "/",
562+
PathType: PathTypePrefix,
563+
MatchRules: []MatchRule{
564+
{
565+
MatchIdx: 0,
566+
RuleIdx: 0,
567+
BackendGroup: expHRNoHostGroups[0],
568+
Source: hrNoHost,
569+
},
570+
},
571+
},
572+
},
573+
},
574+
},
575+
SSLServers: []VirtualServer{},
576+
Upstreams: []Upstream{fooUpstream},
577+
BackendGroups: []BackendGroup{expHRNoHostGroups[0]},
578+
},
579+
msg: "one listener and route without hostnames",
580+
},
519581
{
520582
graph: &graph.Graph{
521583
GatewayClass: &graph.GatewayClass{
@@ -1074,7 +1136,7 @@ func TestBuildConfiguration(t *testing.T) {
10741136
{
10751137
MatchIdx: 0,
10761138
RuleIdx: 1,
1077-
BackendGroup: hr7Groups[1],
1139+
BackendGroup: expHR7Groups[1],
10781140
Source: hr7,
10791141
},
10801142
},
@@ -1086,7 +1148,7 @@ func TestBuildConfiguration(t *testing.T) {
10861148
{
10871149
MatchIdx: 0,
10881150
RuleIdx: 0,
1089-
BackendGroup: hr7Groups[0],
1151+
BackendGroup: expHR7Groups[0],
10901152
Source: hr7,
10911153
},
10921154
},
@@ -1096,7 +1158,7 @@ func TestBuildConfiguration(t *testing.T) {
10961158
},
10971159
SSLServers: []VirtualServer{},
10981160
Upstreams: []Upstream{fooUpstream},
1099-
BackendGroups: []BackendGroup{hr7Groups[0], hr7Groups[1]},
1161+
BackendGroups: []BackendGroup{expHR7Groups[0], expHR7Groups[1]},
11001162
},
11011163
msg: "duplicate paths with different types",
11021164
},

internal/state/graph/httproute.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"github.com/nginxinc/nginx-kubernetes-gateway/internal/state/validation"
1414
)
1515

16+
const wildcardHostname = "~^"
17+
1618
// Rule represents a rule of an HTTPRoute.
1719
type Rule struct {
1820
// BackendRefs is a list of BackendRefs for the rule.
@@ -380,6 +382,13 @@ func findValidListeners(sectionName string, listeners map[string]*Listener) ([]*
380382
func findAcceptedHostnames(listenerHostname *v1beta1.Hostname, routeHostnames []v1beta1.Hostname) []string {
381383
hostname := getHostname(listenerHostname)
382384

385+
if len(routeHostnames) == 0 {
386+
if hostname == "" {
387+
return []string{wildcardHostname}
388+
}
389+
return []string{hostname}
390+
}
391+
383392
match := func(h v1beta1.Hostname) bool {
384393
if hostname == "" {
385394
return true

internal/state/graph/httproute_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,18 @@ func TestFindAcceptedHostnames(t *testing.T) {
10081008
expected: []string{"foo.example.com", "bar.example.com"},
10091009
msg: "nil listener hostname",
10101010
},
1011+
{
1012+
listenerHostname: &listenerHostnameFoo,
1013+
routeHostnames: nil,
1014+
expected: []string{"foo.example.com"},
1015+
msg: "route has empty hostnames",
1016+
},
1017+
{
1018+
listenerHostname: nil,
1019+
routeHostnames: nil,
1020+
expected: []string{wildcardHostname},
1021+
msg: "both listener and route have empty hostnames",
1022+
},
10111023
}
10121024

10131025
for _, test := range tests {

0 commit comments

Comments
 (0)