Skip to content

Commit a7b6059

Browse files
committed
Add validateHostnameProtocolPort to validate that the combination of port, protocol, and name are unique for each listener.
Signed-off-by: Huang Xin <[email protected]>
1 parent 004eb1b commit a7b6059

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

apis/v1beta1/validation/gateway.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2021 The Kubernetes Authors.
2+
Copyright 2023 The Kubernetes Authors.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package validation
1919
import (
2020
"fmt"
2121

22+
"k8s.io/apimachinery/pkg/util/sets"
2223
"k8s.io/apimachinery/pkg/util/validation/field"
2324

2425
gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"
@@ -70,6 +71,7 @@ func validateGatewayListeners(listeners []gatewayv1b1.Listener, path *field.Path
7071
errs = append(errs, validateListenerHostname(listeners, path)...)
7172
errs = append(errs, ValidateTLSCertificateRefs(listeners, path)...)
7273
errs = append(errs, ValidateListenerNames(listeners, path)...)
74+
errs = append(errs, validateHostnameProtocolPort(listeners, path)...)
7375
return errs
7476
}
7577

@@ -133,3 +135,25 @@ func ValidateListenerNames(listeners []gatewayv1b1.Listener, path *field.Path) f
133135
}
134136
return errs
135137
}
138+
139+
// validateHostnameProtocolPort validates that the combination of port, protocol, and name are
140+
// unique for each listener.
141+
func validateHostnameProtocolPort(listeners []gatewayv1b1.Listener, path *field.Path) field.ErrorList {
142+
var errs field.ErrorList
143+
hostnameProtocolPortSets:= sets.Set[string]{}
144+
for i, listener := range listeners {
145+
hostname := new(gatewayv1b1.Hostname)
146+
if listener.Hostname != nil {
147+
hostname = listener.Hostname
148+
}
149+
protocol := listener.Protocol
150+
port := listener.Port
151+
152+
hostnameProtocolPort := fmt.Sprintf("%s:%s:%d", *hostname, protocol, port)
153+
if hostnameProtocolPortSets.Has(hostnameProtocolPort) {
154+
errs = append(errs, field.Forbidden(path.Index(i), fmt.Sprintln("combination of port, protocol, and name must be unique for each listener")))
155+
}
156+
hostnameProtocolPortSets.Insert(hostnameProtocolPort)
157+
}
158+
return errs
159+
}

apis/v1beta1/validation/gateway_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,35 @@ func TestValidateGateway(t *testing.T) {
136136
},
137137
"names are not unique within the Gateway": {
138138
mutate: func(gw *gatewayv1b1.Gateway) {
139+
hostnameFoo := gatewayv1b1.Hostname("foo.com")
140+
hostnameBar := gatewayv1b1.Hostname("bar.com")
139141
gw.Spec.Listeners[0].Name = "foo"
142+
gw.Spec.Listeners[0].Hostname = &hostnameFoo
140143
gw.Spec.Listeners = append(gw.Spec.Listeners, gatewayv1b1.Listener{
141144
Name: "foo",
145+
Hostname: &hostnameBar,
142146
},
143147
)
144148
},
145149
expectErrsOnFields: []string{"spec.listeners[1].name"},
146150
},
151+
"combination of port, protocol, and name are not unique for each listener": {
152+
mutate: func(gw *gatewayv1b1.Gateway) {
153+
hostnameFoo := gatewayv1b1.Hostname("foo.com")
154+
gw.Spec.Listeners[0].Name = "foo"
155+
gw.Spec.Listeners[0].Hostname = &hostnameFoo
156+
gw.Spec.Listeners[0].Protocol = gatewayv1b1.HTTPProtocolType
157+
gw.Spec.Listeners[0].Port = 80
158+
gw.Spec.Listeners = append(gw.Spec.Listeners, gatewayv1b1.Listener{
159+
Name: "bar",
160+
Hostname: &hostnameFoo,
161+
Protocol: gatewayv1b1.HTTPProtocolType,
162+
Port: 80,
163+
},
164+
)
165+
},
166+
expectErrsOnFields: []string{"spec.listeners[1]"},
167+
},
147168
}
148169

149170
for name, tc := range testCases {

0 commit comments

Comments
 (0)